0


SpringBoot集成阿里云OSS、华为云OBS、七牛云、又拍云等上传案例【附白嫖方案】【附源码】

1. 项目背景

唉!本文写起来都是泪点。不是刻意写的本文,主要是对日常用到的文件上传做了一个汇总总结,同时希望可以给用到的小伙伴带来一点帮助吧。

  • 上传本地,这个就不水了,基本做技术的都用到过吧;
  • 阿里云OSS,阿里云是业界巨鳄了吧,用到的人肯定不少吧,不过博主好久不用了,简单记录下;
  • 华为云OBS,工作需要,也简单记录下吧;
  • 七牛云,个人网站最开始使用的图床,目的是为了白嫖10G文件存储。后来网站了升级了https域名,七牛云免费只支持http,https域名加速是收费的。https域名的网站在谷歌上请求图片时会强制升级为https。
  • 又拍云,个人网站目前在用的图床,加入了又拍云联盟,网站底部挂链接,算是推广合作模式吧(对我这种不介意的来说就是白嫖)。速度还行,可以去我的网站看一下:笑小枫

还有腾讯云等等云,暂没用过,就先不整理了,使用都很简单,SDK文档很全,也很简单。

2. 上传思路

分为两点来说。本文的精华也都在这里了,统一思想。

2.1 前端调用上传文件

前端上传的话,应该是我们常用的吧,通过

@RequestParam(value = "file") MultipartFile file

接收,然后转为

InputStream

or

byte[]

or

File

,然后调用上传就可以了,核心也就在这,很简单的,尤其上传到云服务器,装载好配置后,直接调用SDK接口即可。

2.2 通过url地址上传网络文件

通过url上传应该很少用到吧,使用场景呢,例如爬取文章的时候,把网络图片上传到自己的图床;图片库根据url地址迁移。

说到这,突然想起了一个问题,大家写文章的时候,图片上传到图床后在文章内是怎么保存的呢?是全路径还是怎么保存的?如果加速域名换了,或者换图床地址了,需要怎么迁移。希望有经验的大佬可以留言指导!

3. 上传到本地

这个比较简单啦,贴下核心代码吧

  • 在yml配置下上传路径
file:local:maxFileSize:10485760imageFilePath: D:/test/image/
    docFilePath: D:/test/file/
  • 创建配置类,读取配置文件的参数
packagecom.maple.upload.properties;importlombok.Data;importorg.springframework.beans.factory.annotation.Value;importorg.springframework.context.annotation.Configuration;/**
 * 上传本地配置
 *
 * @author 笑小枫
 * @date 2022/7/22
 * @see <a href="https://www.xiaoxiaofeng.com">https://www.xiaoxiaofeng.com</a>
 */@Data@ConfigurationpublicclassLocalFileProperties{// ---------------本地文件配置 start------------------/**
     * 图片存储路径
     */@Value("${file.local.imageFilePath}")privateString imageFilePath;/**
     * 文档存储路径
     */@Value("${file.local.docFilePath}")privateString docFilePath;/**
     * 文件限制大小
     */@Value("${file.local.maxFileSize}")privatelong maxFileSize;// --------------本地文件配置 end-------------------}
  • 创建上传下载工具类
packagecom.maple.upload.util;importcom.maple.upload.properties.LocalFileProperties;importlombok.AllArgsConstructor;importlombok.extern.slf4j.Slf4j;importorg.apache.commons.lang3.StringUtils;importorg.springframework.stereotype.Component;importorg.springframework.web.multipart.MultipartFile;importjavax.servlet.ServletOutputStream;importjavax.servlet.http.HttpServletResponse;importjava.io.File;importjava.io.FileInputStream;importjava.io.IOException;importjava.io.UnsupportedEncodingException;importjava.net.URLDecoder;importjava.nio.charset.StandardCharsets;importjava.nio.file.Files;importjava.text.SimpleDateFormat;importjava.util.*;/**
 * @author 笑小枫
 * @date 2024/1/10
 * @see <a href="https://www.xiaoxiaofeng.com">https://www.xiaoxiaofeng.com</a>
 */@Slf4j@Component@AllArgsConstructorpublicclassLocalFileUtil{privatefinalLocalFileProperties fileProperties;privatestaticfinalList<String>FILE_TYPE_LIST_IMAGE=Arrays.asList("image/png","image/jpg","image/jpeg","image/bmp");/**
     * 上传图片
     */publicStringuploadImage(MultipartFile file){// 检查图片类型String contentType = file.getContentType();if(!FILE_TYPE_LIST_IMAGE.contains(contentType)){thrownewRuntimeException("上传失败,不允许的文件类型");}int size =(int) file.getSize();if(size > fileProperties.getMaxFileSize()){thrownewRuntimeException("文件过大");}String fileName = file.getOriginalFilename();//获取文件后缀String afterName =StringUtils.substringAfterLast(fileName,".");//获取文件前缀String prefName =StringUtils.substringBeforeLast(fileName,".");//获取一个时间毫秒值作为文件名
        fileName =newSimpleDateFormat("yyyyMMddHHmmss").format(newDate())+"_"+ prefName +"."+ afterName;File filePath =newFile(fileProperties.getImageFilePath(), fileName);//判断文件是否已经存在if(filePath.exists()){thrownewRuntimeException("文件已经存在");}//判断文件父目录是否存在if(!filePath.getParentFile().exists()){
            filePath.getParentFile().mkdirs();}try{
            file.transferTo(filePath);}catch(IOException e){
            log.error("图片上传失败", e);thrownewRuntimeException("图片上传失败");}return fileName;}/**
     * 批量上传文件
     */publicList<Map<String,Object>>uploadFiles(MultipartFile[] files){int size =0;for(MultipartFile file : files){
            size =(int) file.getSize()+ size;}if(size > fileProperties.getMaxFileSize()){thrownewRuntimeException("文件过大");}List<Map<String,Object>> fileInfoList =newArrayList<>();for(int i =0; i < files.length; i++){Map<String,Object> map =newHashMap<>();String fileName = files[i].getOriginalFilename();//获取文件后缀String afterName =StringUtils.substringAfterLast(fileName,".");//获取文件前缀String prefName =StringUtils.substringBeforeLast(fileName,".");String fileServiceName =newSimpleDateFormat("yyyyMMddHHmmss").format(newDate())+ i +"_"+ prefName +"."+ afterName;File filePath =newFile(fileProperties.getDocFilePath(), fileServiceName);// 判断文件父目录是否存在if(!filePath.getParentFile().exists()){
                filePath.getParentFile().mkdirs();}try{
                files[i].transferTo(filePath);}catch(IOException e){
                log.error("文件上传失败", e);thrownewRuntimeException("文件上传失败");}
            map.put("fileName", fileName);
            map.put("filePath", filePath);
            map.put("fileServiceName", fileServiceName);
            fileInfoList.add(map);}return fileInfoList;}/**
     * 批量删除文件
     *
     * @param fileNameArr 服务端保存的文件的名数组
     */publicvoiddeleteFile(String[] fileNameArr){for(String fileName : fileNameArr){String filePath = fileProperties.getDocFilePath()+ fileName;File file =newFile(filePath);if(file.exists()){try{Files.delete(file.toPath());}catch(IOException e){
                    e.printStackTrace();
                    log.warn("文件删除失败", e);}}else{
                log.warn("文件: {} 删除失败,该文件不存在", fileName);}}}/**
     * 下载文件
     */publicvoiddownLoadFile(HttpServletResponse response,String fileName)throwsUnsupportedEncodingException{String encodeFileName =URLDecoder.decode(fileName,"UTF-8");File file =newFile(fileProperties.getDocFilePath()+ encodeFileName);// 下载文件if(!file.exists()){thrownewRuntimeException("文件不存在!");}try(FileInputStream inputStream =newFileInputStream(file);ServletOutputStream outputStream = response.getOutputStream()){
            response.reset();//设置响应类型    PDF文件为"application/pdf",WORD文件为:"application/msword", EXCEL文件为:"application/vnd.ms-excel"。
            response.setContentType("application/octet-stream;charset=utf-8");//设置响应的文件名称,并转换成中文编码String afterName =StringUtils.substringAfterLast(fileName,"_");//保存的文件名,必须和页面编码一致,否则乱码
            afterName = response.encodeURL(newString(afterName.getBytes(),StandardCharsets.ISO_8859_1.displayName()));
            response.setHeader("Content-type","application-download");//attachment作为附件下载;inline客户端机器有安装匹配程序,则直接打开;注意改变配置,清除缓存,否则可能不能看到效果
            response.addHeader("Content-Disposition","attachment;filename="+ afterName);
            response.addHeader("filename", afterName);//将文件读入响应流int length =1024;byte[] buf =newbyte[1024];int readLength = inputStream.read(buf,0, length);while(readLength !=-1){
                outputStream.write(buf,0, readLength);
                readLength = inputStream.read(buf,0, length);}
            outputStream.flush();}catch(Exception e){
            e.printStackTrace();}}}

访问图片的话,可以通过重写

WebMvcConfigurer

addResourceHandlers

方法来实现。

通过请求

/local/images/**

将链接虚拟映射到我们配置的

localFileProperties.getImageFilePath()

下,文件访问同理。

详细代码如下

packagecom.maple.upload.config;importcom.maple.upload.properties.LocalFileProperties;importlombok.AllArgsConstructor;importorg.springframework.context.annotation.Configuration;importorg.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;importorg.springframework.web.servlet.config.annotation.WebMvcConfigurer;/**
 * @author 笑小枫 <https://www.xiaoxiaofeng.com/>
 * @date 2024/1/10
 */@Configuration@AllArgsConstructorpublicclassLocalFileConfigimplementsWebMvcConfigurer{privatefinalLocalFileProperties localFileProperties;@OverridepublicvoidaddResourceHandlers(ResourceHandlerRegistry registry){// 重写方法// 修改tomcat 虚拟映射// 定义图片存放路径
        registry.addResourceHandler("/local/images/**").addResourceLocations("file:"+ localFileProperties.getImageFilePath());//定义文档存放路径
        registry.addResourceHandler("/local/doc/**").addResourceLocations("file:"+ localFileProperties.getDocFilePath());}}
  • controller调用代码
packagecom.maple.upload.controller;importcom.maple.upload.util.LocalFileUtil;importlombok.AllArgsConstructor;importlombok.extern.slf4j.Slf4j;importorg.springframework.web.bind.annotation.*;importorg.springframework.web.multipart.MultipartFile;importjavax.servlet.http.HttpServletResponse;importjava.util.List;importjava.util.Map;/**
 * 文件相关操作接口
 *
 * @author 笑小枫
 * @date 2024/1/10
 * @see <a href="https://www.xiaoxiaofeng.com">https://www.xiaoxiaofeng.com</a>
 */@Slf4j@RestController@AllArgsConstructor@RequestMapping("/local")publicclassLocalFileController{privatefinalLocalFileUtil fileUtil;/**
     * 图片上传
     */@PostMapping("/uploadImage")publicStringuploadImage(@RequestParam(value ="file")MultipartFile file){if(file.isEmpty()){thrownewRuntimeException("图片内容为空,上传失败!");}return fileUtil.uploadImage(file);}/**
     * 文件批量上传
     */@PostMapping("/uploadFiles")publicList<Map<String,Object>>uploadFiles(@RequestParam(value ="file")MultipartFile[] files){return fileUtil.uploadFiles(files);}/**
     * 批量删除文件
     */@PostMapping("/deleteFiles")publicvoiddeleteFiles(@RequestParam(value ="files")String[] files){
        fileUtil.deleteFile(files);}/**
     * 文件下载功能
     */@GetMapping(value ="/download/{fileName:.*}")publicvoiddownload(@PathVariable("fileName")String fileName,HttpServletResponse response){try{
            fileUtil.downLoadFile(response, fileName);}catch(Exception e){
            log.error("文件下载失败", e);}}}

调用上传图片的接口,可以看到图片已经上传成功。

image-20240116102717345

通过请求

/local/images/**

将链接虚拟映射我们图片上。

image-20240116103037587

批量上传,删除等操作就不一一演示截图了,代码已贴,因为是先写的demo,后写的文章,获取代码片贴的有遗漏,如有遗漏,可以去文章底部查看源码地址。

4. 上传阿里云OSS

阿里云OSS官方sdk使用文档:https://help.aliyun.com/zh/oss/developer-reference/java

阿里云OSS操作指南:https://help.aliyun.com/zh/oss/user-guide

公共云下OSS Region和Endpoint对照表:https://help.aliyun.com/zh/oss/user-guide/regions-and-endpoints

更多公共云下OSS Region和Endpoint对照,参考上面链接

image-20240116103832968

  • 引入oss sdk依赖
<!-- 阿里云OSS --><dependency><groupId>com.aliyun.oss</groupId><artifactId>aliyun-sdk-oss</artifactId><version>3.8.1</version></dependency>
  • 配置上传配置信息
file:oss:bucketName: mapleBucket
    accessKeyId: your ak
    secretAccessKey: your sk
    endpoint: oss-cn-shanghai.aliyuncs.com
    showUrl: cdn地址-file.xiaoxiaofeng.com
  • 创建配置类,读取配置文件的参数
/*
 * Copyright (c) 2018-2999 上海合齐软件科技科技有限公司 All rights reserved.
 *
 *
 *
 * 未经允许,不可做商业用途!
 *
 * 版权所有,侵权必究!
 */packagecom.maple.upload.properties;importlombok.Data;importorg.springframework.beans.factory.annotation.Value;importorg.springframework.context.annotation.Configuration;/**
 * 阿里云OSS配置
 *
 * @author 笑小枫 <https://www.xiaoxiaofeng.com/>
 * @date 2024/1/10
 */@Data@ConfigurationpublicclassAliOssProperties{@Value("${file.oss.bucketName}")privateString bucketName;@Value("${file.oss.accessKeyId}")privateString accessKeyId;@Value("${file.oss.secretAccessKey}")privateString secretAccessKey;@Value("${file.oss.endpoint}")privateString endpoint;@Value("${file.oss.showUrl}")privateString showUrl;}
  • 上传工具类
packagecom.maple.upload.util;importcom.aliyun.oss.OSS;importcom.aliyun.oss.OSSClientBuilder;importcom.aliyun.oss.model.PutObjectResult;importcom.maple.upload.properties.AliOssProperties;importlombok.AllArgsConstructor;importlombok.extern.slf4j.Slf4j;importorg.apache.commons.lang3.StringUtils;importorg.springframework.stereotype.Component;importorg.springframework.web.multipart.MultipartFile;importjava.io.InputStream;/**
 * 阿里云OSS 对象存储工具类
 * 阿里云OSS官方sdk使用文档:https://help.aliyun.com/zh/oss/developer-reference/java
 * 阿里云OSS操作指南:https://help.aliyun.com/zh/oss/user-guide
 * 
 * @author 笑小枫 <https://www.xiaoxiaofeng.com/>
 * @date 2024/1/15
 */@Slf4j@Component@AllArgsConstructorpublicclassAliOssUtil{privatefinalAliOssProperties aliOssProperties;publicStringuploadFile(MultipartFile file){String fileName = file.getOriginalFilename();if(StringUtils.isBlank(fileName)){thrownewRuntimeException("获取文件信息失败");}// 组建上传的文件名称,命名规则可自定义更改String objectKey =FileCommonUtil.setFilePath("xiaoxiaofeng")+FileCommonUtil.setFileName("xxf", fileName.substring(fileName.lastIndexOf(".")));//构造一个OSS对象的配置类OSS ossClient =newOSSClientBuilder().build(aliOssProperties.getEndpoint(), aliOssProperties.getAccessKeyId(), aliOssProperties.getSecretAccessKey());try(InputStream inputStream = file.getInputStream()){
            log.info(String.format("阿里云OSS上传开始,原文件名:%s,上传后的文件名:%s", fileName, objectKey));PutObjectResult result = ossClient.putObject(aliOssProperties.getBucketName(), objectKey, inputStream);
            log.info(String.format("阿里云OSS上传结束,文件名:%s,返回结果:%s", objectKey, result.toString()));return aliOssProperties.getShowUrl()+ objectKey;}catch(Exception e){
            log.error("调用阿里云OSS失败", e);thrownewRuntimeException("调用阿里云OSS失败");}}}

因为篇幅问题,controller就不贴了。暂时没有阿里云oss的资源了,这里就不做测试,小伙伴在使用过程中如有问题,麻烦留言告诉我下!

5. 上传华为云OBS

华为云OBS官方sdk使用文档:https://support.huaweicloud.com/sdk-java-devg-obs/obs_21_0101.html

华为云OBS操作指南:https://support.huaweicloud.com/ugobs-obs/obs_41_0002.html

华为云各服务应用区域和各服务的终端节点:https://developer.huaweicloud.com/endpoint?OBS

  • 引入sdk依赖
<!-- 华为云OBS --><dependency><groupId>com.huaweicloud</groupId><artifactId>esdk-obs-java-bundle</artifactId><version>3.21.8</version></dependency>
  • 配置上传配置信息
file:obs:bucketName: mapleBucket
    accessKey: your ak
    secretKey: your sk
    endPoint: obs.cn-east-2.myhuaweicloud.com
    showUrl: cdn地址-file.xiaoxiaofeng.com
  • 创建配置类,读取配置文件的参数
packagecom.maple.upload.properties;importlombok.Data;importorg.springframework.beans.factory.annotation.Value;importorg.springframework.context.annotation.Configuration;/**
 * 华为云上传配置
 *
 * @author 笑小枫 <https://www.xiaoxiaofeng.com/>
 * @date 2024/1/10
 */@Data@ConfigurationpublicclassHwyObsProperties{@Value("${file.obs.bucketName}")privateString bucketName;@Value("${file.obs.accessKey}")privateString accessKey;@Value("${file.obs.secretKey}")privateString secretKey;@Value("${file.obs.endPoint}")privateString endPoint;@Value("${file.obs.showUrl}")privateString showUrl;}
  • 上传工具类
packagecom.maple.upload.util;importcom.alibaba.fastjson.JSON;importcom.maple.upload.bean.HwyObsModel;importcom.maple.upload.properties.HwyObsProperties;importcom.obs.services.ObsClient;importcom.obs.services.exception.ObsException;importcom.obs.services.model.PostSignatureRequest;importcom.obs.services.model.PostSignatureResponse;importcom.obs.services.model.PutObjectResult;importlombok.AllArgsConstructor;importlombok.extern.slf4j.Slf4j;importorg.apache.commons.lang3.StringUtils;importorg.springframework.stereotype.Component;importorg.springframework.web.multipart.MultipartFile;importjava.io.IOException;importjava.io.InputStream;/**
 * 华为云OBS 对象存储工具类
 * 华为云OBS官方sdk使用文档:https://support.huaweicloud.com/sdk-java-devg-obs/obs_21_0101.html
 * 华为云OBS操作指南:https://support.huaweicloud.com/ugobs-obs/obs_41_0002.html
 * 华为云各服务应用区域和各服务的终端节点:https://developer.huaweicloud.com/endpoint?OBS
 *
 * @author 笑小枫
 * @date 2022/7/22
 * @see <a href="https://www.xiaoxiaofeng.com">https://www.xiaoxiaofeng.com</a>
 */@Slf4j@Component@AllArgsConstructorpublicclassHwyObsUtil{privatefinalHwyObsProperties fileProperties;/**
     * 上传华为云obs文件存储
     *
     * @param file 文件
     * @return 文件访问路径, 如果配置CDN,这里直接返回CDN+文件名(objectKey)
     */publicStringuploadFileToObs(MultipartFile file){String fileName = file.getOriginalFilename();if(StringUtils.isBlank(fileName)){thrownewRuntimeException("获取文件信息失败");}// 文件类型String fileType = fileName.substring(file.getOriginalFilename().lastIndexOf("."));// 组建上传的文件名称,命名规则可自定义更改String objectKey =FileCommonUtil.setFilePath("")+FileCommonUtil.setFileName(null, fileType);PutObjectResult putObjectResult;try(InputStream inputStream = file.getInputStream();ObsClient obsClient =newObsClient(fileProperties.getAccessKey(), fileProperties.getSecretKey(), fileProperties.getEndPoint())){
            log.info(String.format("华为云obs上传开始,原文件名:%s,上传后的文件名:%s", fileName, objectKey));
            putObjectResult = obsClient.putObject(fileProperties.getBucketName(), objectKey, inputStream);
            log.info(String.format("华为云obs上传结束,文件名:%s,返回结果:%s", objectKey,JSON.toJSONString(putObjectResult)));}catch(ObsException|IOException e){
            log.error("华为云obs上传文件失败", e);thrownewRuntimeException("华为云obs上传文件失败,请重试");}if(putObjectResult.getStatusCode()==200){return putObjectResult.getObjectUrl();}else{thrownewRuntimeException("华为云obs上传文件失败,请重试");}}/**
     * 获取华为云上传token,将token返回给前端,然后由前端上传,这样文件不占服务器端带宽
     *
     * @param fileName 文件名称
     * @return
     */publicHwyObsModelgetObsConfig(String fileName){if(StringUtils.isBlank(fileName)){thrownewRuntimeException("The fileName cannot be empty.");}String obsToken;String objectKey =null;try(ObsClient obsClient =newObsClient(fileProperties.getAccessKey(), fileProperties.getSecretKey(), fileProperties.getEndPoint())){String fileType = fileName.substring(fileName.lastIndexOf("."));// 组建上传的文件名称,命名规则可自定义更改
            objectKey =FileCommonUtil.setFilePath("")+FileCommonUtil.setFileName("", fileType);PostSignatureRequest request =newPostSignatureRequest();// 设置表单上传请求有效期,单位:秒
            request.setExpires(3600);
            request.setBucketName(fileProperties.getBucketName());if(StringUtils.isNotBlank(objectKey)){
                request.setObjectKey(objectKey);}PostSignatureResponse response = obsClient.createPostSignature(request);
            obsToken = response.getToken();}catch(ObsException|IOException e){
            log.error("华为云obs上传文件失败", e);thrownewRuntimeException("华为云obs上传文件失败,请重试");}HwyObsModel obsModel =newHwyObsModel();
        obsModel.setBucketName(fileProperties.getBucketName());
        obsModel.setEndPoint(fileProperties.getEndPoint());
        obsModel.setToken(obsToken);
        obsModel.setObjectKey(objectKey);
        obsModel.setShowUrl(fileProperties.getShowUrl());return obsModel;}}

篇幅问题,不贴controller和测试截图了,完整代码参考文章底部源码吧,思想明白了,别的都大差不差。

6. 上传七牛云

七牛云官方sdk:https://developer.qiniu.com/kodo/1239/java

七牛云存储区域表链接:https://developer.qiniu.com/kodo/1671/region-endpoint-fq

  • 引入sdk依赖
<!-- 七牛云 --><dependency><groupId>com.qiniu</groupId><artifactId>qiniu-java-sdk</artifactId><version>7.2.29</version></dependency>
  • 配置上传配置信息
file:qiniuyun:bucket: mapleBucket
    accessKey: your ak
    secretKey: your sk
    regionId: z1
    showUrl: cdn地址-file.xiaoxiaofeng.com
  • 创建配置类,读取配置文件的参数
packagecom.maple.upload.properties;importlombok.Data;importorg.springframework.beans.factory.annotation.Value;importorg.springframework.context.annotation.Configuration;/**
 * 七牛云配置
 *
 * @author 笑小枫 <https://www.xiaoxiaofeng.com/>
 * @date 2024/1/10
 */@Data@ConfigurationpublicclassQiNiuProperties{@Value("${file.qiniuyun.accessKey}")privateString accessKey;@Value("${file.qiniuyun.secretKey}")privateString secretKey;@Value("${file.qiniuyun.bucket}")privateString bucket;@Value("${file.qiniuyun.regionId}")privateString regionId;@Value("${file.qiniuyun.showUrl}")privateString showUrl;}
  • 上传工具类,注意有一个区域转换,如后续有新增,qiNiuConfig这里需要调整一下
packagecom.maple.upload.util;importcom.maple.upload.properties.QiNiuProperties;importcom.qiniu.http.Response;importcom.qiniu.storage.Configuration;importcom.qiniu.storage.Region;importcom.qiniu.storage.UploadManager;importcom.qiniu.util.Auth;importlombok.AllArgsConstructor;importlombok.extern.slf4j.Slf4j;importorg.apache.commons.lang3.StringUtils;importorg.springframework.stereotype.Component;importorg.springframework.web.multipart.MultipartFile;importjava.io.InputStream;importjava.util.Objects;/**
 * 
 * 七牛云 对象存储工具类
 * 七牛云官方sdk:https://developer.qiniu.com/kodo/1239/java
 * 七牛云存储区域表链接:https://developer.qiniu.com/kodo/1671/region-endpoint-fq
 * 
 * @author 笑小枫 <https://www.xiaoxiaofeng.com/>
 * @date 2022/3/24
 */@Slf4j@Component@AllArgsConstructorpublicclassQiNiuYunUtil{privatefinalQiNiuProperties qiNiuProperties;publicStringuploadFile(MultipartFile file){String fileName = file.getOriginalFilename();if(StringUtils.isBlank(fileName)){thrownewRuntimeException("获取文件信息失败");}// 组建上传的文件名称,命名规则可自定义更改String objectKey =FileCommonUtil.setFilePath("xiaoxiaofeng")+FileCommonUtil.setFileName("xxf", fileName.substring(fileName.lastIndexOf(".")));//构造一个带指定 Region 对象的配置类Configuration cfg =qiNiuConfig(qiNiuProperties.getRegionId());//...其他参数参考类注释UploadManager uploadManager =newUploadManager(cfg);try(InputStream inputStream = file.getInputStream()){Auth auth =Auth.create(qiNiuProperties.getAccessKey(), qiNiuProperties.getSecretKey());String upToken = auth.uploadToken(qiNiuProperties.getBucket());
            log.info(String.format("七牛云上传开始,原文件名:%s,上传后的文件名:%s", fileName, objectKey));Response response = uploadManager.put(inputStream, objectKey, upToken,null,null);
            log.info(String.format("七牛云上传结束,文件名:%s,返回结果:%s", objectKey, response.toString()));return qiNiuProperties.getShowUrl()+ objectKey;}catch(Exception e){
            log.error("调用七牛云失败", e);thrownewRuntimeException("调用七牛云失败");}}privatestaticConfigurationqiNiuConfig(String zone){Region region =null;if(Objects.equals(zone,"z1")){
            region =Region.huabei();}elseif(Objects.equals(zone,"z0")){
            region =Region.huadong();}elseif(Objects.equals(zone,"z2")){
            region =Region.huanan();}elseif(Objects.equals(zone,"na0")){
            region =Region.beimei();}elseif(Objects.equals(zone,"as0")){
            region =Region.xinjiapo();}returnnewConfiguration(region);}}

篇幅问题,不贴controller和测试截图了,完整代码参考文章底部源码吧,思想明白了,别的都大差不差。

7. 上传又拍云

又拍云客户端配置:https://help.upyun.com/knowledge-base/quick_start/

又拍云官方sdk:https://github.com/upyun/java-sdk

  • 引入sdk依赖
<!-- 又拍云OSS --><dependency><groupId>com.upyun</groupId><artifactId>java-sdk</artifactId><version>4.2.3</version></dependency>
  • 配置上传配置信息
file:upy:bucketName: mapleBucket
    userName: 操作用户名称
    password: 操作用户密码
    showUrl: cdn地址-file.xiaoxiaofeng.com
  • 创建配置类,读取配置文件的参数
packagecom.maple.upload.properties;importlombok.Data;importorg.springframework.beans.factory.annotation.Value;importorg.springframework.context.annotation.Configuration;/**
 * 又拍云上传配置
 *
 * @author 笑小枫 <https://www.xiaoxiaofeng.com/>
 * @date 2024/1/10
 */@Data@ConfigurationpublicclassUpyOssProperties{@Value("${file.upy.bucketName}")privateString bucketName;@Value("${file.upy.userName}")privateString userName;@Value("${file.upy.password}")privateString password;/**
     * 加速域名
     */@Value("${file.upy.showUrl}")privateString showUrl;}
  • 上传工具类
packagecom.maple.upload.util;importcom.maple.upload.properties.UpyOssProperties;importcom.upyun.RestManager;importcom.upyun.UpException;importlombok.AllArgsConstructor;importlombok.extern.slf4j.Slf4j;importokhttp3.Response;importorg.apache.commons.io.IOUtils;importorg.apache.commons.lang3.StringUtils;importorg.springframework.stereotype.Component;importorg.springframework.web.multipart.MultipartFile;importjava.io.IOException;importjava.io.InputStream;importjava.net.URI;/**
 * 又拍云 对象存储工具类
 * 又拍云客户端配置:https://help.upyun.com/knowledge-base/quick_start/
 * 又拍云官方sdk:https://github.com/upyun/java-sdk
 *
 * @author 笑小枫
 * @date 2022/7/22
 * @see <a href="https://www.xiaoxiaofeng.com">https://www.xiaoxiaofeng.com</a>
 */@Slf4j@Component@AllArgsConstructorpublicclassUpyOssUtil{privatefinalUpyOssProperties fileProperties;/**
     * 根据url上传文件到又拍云
     */publicStringuploadUpy(String url){// 组建上传的文件名称,命名规则可自定义更改String fileName =FileCommonUtil.setFilePath("xiaoxiaofeng")+FileCommonUtil.setFileName("xxf", url.substring(url.lastIndexOf(".")));RestManager restManager =newRestManager(fileProperties.getBucketName(), fileProperties.getUserName(), fileProperties.getPassword());URI u =URI.create(url);try(InputStream inputStream = u.toURL().openStream()){byte[] bytes =IOUtils.toByteArray(inputStream);Response response = restManager.writeFile(fileName, bytes,null);if(response.isSuccessful()){return fileProperties.getShowUrl()+ fileName;}}catch(IOException|UpException e){
            log.error("又拍云oss上传文件失败", e);}thrownewRuntimeException("又拍云oss上传文件失败,请重试");}/**
     * MultipartFile上传文件到又拍云
     */publicStringuploadUpy(MultipartFile file){String fileName = file.getOriginalFilename();if(StringUtils.isBlank(fileName)){thrownewRuntimeException("获取文件信息失败");}// 组建上传的文件名称,命名规则可自定义更改String objectKey =FileCommonUtil.setFilePath("xiaoxiaofeng")+FileCommonUtil.setFileName("xxf", fileName.substring(fileName.lastIndexOf(".")));RestManager restManager =newRestManager(fileProperties.getBucketName(), fileProperties.getUserName(), fileProperties.getPassword());try(InputStream inputStream = file.getInputStream()){
            log.info(String.format("又拍云上传开始,原文件名:%s,上传后的文件名:%s", fileName, objectKey));Response response = restManager.writeFile(objectKey, inputStream,null);
            log.info(String.format("又拍云上传结束,文件名:%s,返回结果:%s", objectKey, response.isSuccessful()));if(response.isSuccessful()){return fileProperties.getShowUrl()+ objectKey;}}catch(IOException|UpException e){
            log.error("又拍云oss上传文件失败", e);}thrownewRuntimeException("又拍云oss上传文件失败,请重试");}}

篇幅问题,不贴controller和测试截图了,完整代码参考文章底部源码吧,思想明白了,别的都大差不差。

8. 项目源码

本文到此就结束了,如果帮助到你了,帮忙点个赞👍

本文源码:https://github.com/hack-feng/maple-product/tree/main/maple-file-upload

🐾我是笑小枫,全网皆可搜的【笑小枫】


本文转载自: https://blog.csdn.net/qq_34988304/article/details/136182961
版权归原作者 笑小枫 所有, 如有侵权,请联系我们删除。

“SpringBoot集成阿里云OSS、华为云OBS、七牛云、又拍云等上传案例【附白嫖方案】【附源码】”的评论:

还没有评论