Java实现上传网络图片到七牛云存储详解
穆雄雄 人气:0前言
最近阳了,第二条杠红的发紫,真难受啊,但是吧,博客上有个bug,不解决感觉比阳了还难受。
话还是要从博客的图片显示不出来这里说起,当时做的时候,在发文章这里,感觉没有封面的话,文章会很孤单,所以就设计了个封面这块儿。但是,封面如果太邋遢也还不如没有。
所以我就从网上的一个接口里面随机取的一些精美图片,本来好好的,结果今天一看,那个接口报错403了,当时就想着,这样做太依赖别人了,什么东西都得掌控在自己手里,不然出问题了难受的还是自己。
正好借这个机会,就重新设计了下,先从接口中取,如果接口中的图片能看,则用这个图片,顺便将这个图片传至七牛云存储中,否则就随机从七牛云存储中指定些图片展示出来,这样就不会受制于人。
效果图
直接将图片传至七牛云中,给我们返回该图片的地址。
代码实现
因为七牛云上传图片的时候,传递的是MultipartFile类型,所以我们需要将网络图片utl转换成流,然后在转换成MultipartFile,接着使用七牛云提供的方法上传即可。
下面我们先看看怎么将网络url转换成MultipartFile,这个代码网上很多,大家可以随便搜一个放上来就行,我这边封装了个工具类:FilesUtil
package com.shiyi.util; import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; import org.apache.http.entity.ContentType; import org.apache.pdfbox.io.IOUtils; import org.springframework.mock.web.MockMultipartFile; import org.springframework.web.multipart.MultipartFile; import java.io.*; import java.net.HttpURLConnection; import java.net.URL; /** * @author: muxiongxiong * @date: 2022年12月29日 15:35 * 博客:https://blog.csdn.net/qq_34137397 * 个人站:https://www.穆雄雄.com * 个人站:https://www.muxiongxiong.cn * @Description: 类的描述 */ public class FilesUtil { /** * 根据地址获得数据的输入流 * * @param strUrl 网络连接地址 * @return url的输入流 */ public static InputStream getInputStreamByUrl(String strUrl) { HttpURLConnection conn = null; try { URL url = new URL(strUrl); conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("GET"); conn.setConnectTimeout(20 * 1000); final ByteArrayOutputStream output = new ByteArrayOutputStream(); IOUtils.copy(conn.getInputStream(), output); return new ByteArrayInputStream(output.toByteArray()); } catch (Exception e) { e.printStackTrace(); } finally { try { if (conn != null) { conn.disconnect(); } } catch (Exception e) { e.printStackTrace(); } } return null; } /** * 将网络地址转换成MultipartFile * @param strUrl * @return */ public static MultipartFile onlineAddressTransferFile(String strUrl){ MultipartFile file = null; try { String fileName = strUrl.substring(strUrl.lastIndexOf("/") + 1); InputStream stream = getInputStreamByUrl(strUrl); if (!ObjectUtils.isEmpty(stream)) { file = new MockMultipartFile(fileName, fileName, "", stream); return file; } }catch (Exception exception){ exception.printStackTrace(); } return file; } }
在调用的时候我们这样调:
/** * 手动上传网络图片 */ @GetMapping(value = "/uploadFm") public ResponseResult uploadFm(){ MultipartFile multipartFile = FilesUtil.onlineAddressTransferFile("https://img-community.csdnimg.cn/images/86f32eac875e42af9ed9e91b809dc7d8.png"); return cloudOssService.upload(multipartFile); }
剩下的就是七牛云里面的方法了,这边一起放上来吧:
CloudOssService接口代码:
package com.shiyi.service; import com.shiyi.common.ResponseResult; import org.springframework.web.multipart.MultipartFile; public interface CloudOssService { /** * 上传 * @param file 文件 * @return */ ResponseResult upload(MultipartFile file); /** * 批量删除文件 * @param key 文件名 * @return */ ResponseResult delBatchFile(String ...key); }
CloudOssServiceImpl
实现类,主要是实现CloudOssService
接口的:
package com.shiyi.service.impl; import com.shiyi.common.ResponseResult; import com.shiyi.enums.FileUploadModelEnum; import com.shiyi.service.CloudOssService; import com.shiyi.service.SystemConfigService; import com.shiyi.strategy.context.FileUploadStrategyContext; import lombok.RequiredArgsConstructor; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; import org.springframework.stereotype.Service; import org.springframework.web.multipart.MultipartFile; import java.util.Objects; @Service @RequiredArgsConstructor public class CloudOssServiceImpl implements CloudOssService { private final SystemConfigService systemConfigService; private final FileUploadStrategyContext fileUploadStrategyContext; private String strategy; /** * 上传文件 * @param file * @return */ @Override public ResponseResult upload(MultipartFile file) { if (file.getSize() > 1024 * 1024 * 10) { return ResponseResult.error("文件大小不能大于10M"); } //获取文件后缀 String suffix = Objects.requireNonNull(file.getOriginalFilename()).substring(file.getOriginalFilename().lastIndexOf(".") + 1); if (!"jpg,jpeg,gif,png".toUpperCase().contains(suffix.toUpperCase())) { return ResponseResult.error("请选择jpg,jpeg,gif,png格式的图片"); } getFileUploadWay(); String key = fileUploadStrategyContext.executeFileUploadStrategy(strategy, file, suffix); return ResponseResult.success(key); } /** * 删除文件 * @param key * @return */ @Override public ResponseResult delBatchFile(String ...key) { getFileUploadWay(); Boolean isSuccess = fileUploadStrategyContext.executeDeleteFileStrategy(strategy, key); if (!isSuccess) { return ResponseResult.error("删除文件失败"); } return ResponseResult.success(); } private void getFileUploadWay() { strategy = FileUploadModelEnum.getStrategy(systemConfigService.getCustomizeOne().getFileUploadWay()); } }
最后是文件上传策略上下文类:
package com.shiyi.strategy.context; import com.shiyi.strategy.FileUploadStrategy; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.web.multipart.MultipartFile; import java.util.Map; /** * @apiNote 文件上传策略上下文 */ @Service @RequiredArgsConstructor public class FileUploadStrategyContext { private final Map<String, FileUploadStrategy> fileUploadStrategyMap; /** * 执行文件上传策略 * * @param file 文件对象 * @return {@link String} 文件名 */ public String executeFileUploadStrategy(String fileUploadMode, MultipartFile file,String suffix) { return fileUploadStrategyMap.get(fileUploadMode).fileUpload(file,suffix); } /** * 删除文件策略 * @param fileUploadMode * @param key * @return */ public Boolean executeDeleteFileStrategy(String fileUploadMode,String ...key) { return fileUploadStrategyMap.get(fileUploadMode).deleteFile(key); } }
QiNiuUploadStrategyImpl
实现类的代码:
package com.shiyi.strategy.imp; import com.alibaba.fastjson.JSON; import com.qiniu.common.QiniuException; import com.qiniu.http.Response; import com.qiniu.storage.BucketManager; import com.qiniu.storage.Configuration; import com.qiniu.storage.Region; import com.qiniu.storage.UploadManager; import com.qiniu.storage.model.BatchStatus; import com.qiniu.storage.model.DefaultPutRet; import com.qiniu.storage.model.FileInfo; import com.qiniu.util.Auth; import com.shiyi.entity.SystemConfig; import com.shiyi.enums.QiNiuAreaEnum; import com.shiyi.service.SystemConfigService; import com.shiyi.strategy.FileUploadStrategy; import com.shiyi.util.UUIDUtils; import lombok.RequiredArgsConstructor; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service; import org.springframework.web.multipart.MultipartFile; import javax.annotation.PostConstruct; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; @Service("qiNiuUploadStrategyImpl") @RequiredArgsConstructor public class QiNiuUploadStrategyImpl implements FileUploadStrategy { private final Logger logger = LoggerFactory.getLogger(QiNiuUploadStrategyImpl.class); private final SystemConfigService systemConfigService; private String qi_niu_accessKey; private String qi_niu_secretKey; private String qi_niu_bucket; private Region region; private String qi_niu_url; @PostConstruct private void init(){ SystemConfig systemConfig = systemConfigService.getCustomizeOne(); qi_niu_accessKey = systemConfig.getQiNiuAccessKey(); qi_niu_secretKey = systemConfig.getQiNiuSecretKey(); qi_niu_bucket = systemConfig.getQiNiuBucket(); qi_niu_url = systemConfig.getQiNiuPictureBaseUrl(); region = QiNiuAreaEnum.getRegion(systemConfig.getQiNiuArea()); } public void list() { Configuration configuration = new Configuration(region); Auth auth = Auth.create(qi_niu_accessKey, qi_niu_secretKey); BucketManager bucketManager = new BucketManager(auth,configuration); BucketManager.FileListIterator fileListIterator = bucketManager.createFileListIterator(qi_niu_bucket, null, 1000, null); while (fileListIterator.hasNext()) { FileInfo[] next = fileListIterator.next(); for (FileInfo fileInfo : next) { logger.info("文件打印开始,文件名:{}",qi_niu_url + fileInfo.key); logger.info("文件类别打印开始,类别:{}",fileInfo.mimeType); logger.info("文件大小打印开始,大小:{}",fileInfo.fsize); } } } /** * 七牛云文件上传 * @param file 文件 * @param suffix 后缀 * @return */ @Override public String fileUpload(MultipartFile file,String suffix) { String key = null; //构造一个带指定 Region 对象的配置类 Configuration cfg = new Configuration(region); //...其他参数参考类注释 UploadManager uploadManager = new UploadManager(cfg); //...生成上传凭证,然后准备上传 Auth auth = Auth.create(qi_niu_accessKey, qi_niu_secretKey); String upToken = auth.uploadToken(qi_niu_bucket); InputStream inputStream = null; try { inputStream = file.getInputStream(); //这里需要处理一下,不能让每次上去都是个UUID的文件名 Response response = uploadManager.put(inputStream, "blog/"+UUIDUtils.getUuid() + "." + suffix, upToken,null,null); //解析上传成功的结果 DefaultPutRet putRet = JSON.parseObject(response.bodyString(),DefaultPutRet.class); key = qi_niu_url + putRet.key; } catch (QiniuException ex) { Response r = ex.response; logger.error("QiniuException:{}",r.toString()); } catch (IOException e) { e.printStackTrace(); }finally { if (inputStream != null){ try { inputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } return key; } /** * 批量删除文件 * @return */ @Override public Boolean deleteFile(String ...keys) { //构造一个带指定 Region 对象的配置类 Configuration cfg = new Configuration(Region.region2()); //...其他参数参考类注释 Auth auth = Auth.create(qi_niu_accessKey, qi_niu_secretKey); BucketManager bucketManager = new BucketManager(auth, cfg); try { BucketManager.BatchOperations batchOperations = new BucketManager.BatchOperations(); batchOperations.addDeleteOp(qi_niu_bucket, keys); Response response = bucketManager.batch(batchOperations); BatchStatus[] batchStatusList = response.jsonToObject(BatchStatus[].class); for (int i = 0; i < keys.length; i++) { BatchStatus status = batchStatusList[i]; String key = keys[i]; System.out.print(key + "\t"); if (status.code == 200) { System.out.println("delete success"); } else { System.out.println(status.data.error); } } return true; } catch (QiniuException ex) { System.err.println(ex.response.toString()); return false; } } }
然后我们从接口里面直接调用即可上传上去。
加载全部内容