spring boot使用七牛云做文件上传并返回图片地址

在做上传的时候,因为考虑到以后用户量很多的时候,同时很多人上传 2MB 的图片时,服务器肯定吃不消,到时候体验就差了。所以很是准备使用第三方的云存储,本文介绍 SpringBoot 下如何将图片存储到七牛云上。

 

一、引入 Java SDK

官方文档:https://developer.qiniu.com/kodo/sdk/1239/java

在 pom.xml 里添加以下依赖

  1. <dependency>
  2.   <groupId>com.qiniu</groupId>
  3.   <artifactId>qiniu-java-sdk</artifactId>
  4.   <version>[7.2.0, 7.2.99]</version>
  5. </dependency>

这里的version指定了一个版本范围,每次更新pom.xml的时候会尝试去下载7.2.x版本中的最新版本,你可以手动指定一个固定的版本。

二、创建存储空间,绑定授权信息

1、先创建一个存储空间(bucket),点此

spring boot使用七牛云做文件上传并返回图片地址

在创建仓库的时候,注意选择机房位置,下面配置类里要选择指定的机房

 

2、在个人中心,密钥管理里获取

spring boot使用七牛云做文件上传并返回图片地址

在这里可以获得 Access 和 Key

3、在 application.properties 里填写如下内容

  1. qiniu.accessKey=3QBQHJh_Fo-BYbbrcmBOUf5Z2ArbY3qm5vCfqn3e
  2. qiniu.secretKey=GWLhKUhHcHClUjgP6coGfNTtmUsTzCbnSNDDN9kE
  3. qiniu.bucket=codergroup
  4. spring.servlet.multipart.enabled=true
  5. spring.servlet.multipart.location=/Users/liuyanzhao/Documents/public
  6. spring.servlet.multipart.file-size-threshold=5MB
  7. spring.servlet.multipart.max-request-size=20MB

这里的四个参数请按自己的七牛云账户里面的信息填写。

 

4、创建一个配置类,方便后面操作

QiNiuProperties.java

  1. import lombok.Data;
  2. import org.springframework.boot.context.properties.ConfigurationProperties;
  3. import org.springframework.stereotype.Component;
  4. /**
  5.  * @author 言曌
  6.  * @date 2018/4/5 下午9:36
  7.  */
  8. @Component
  9. @Data
  10. @ConfigurationProperties(prefix = "qiniu")
  11. public class QiNiuProperties {
  12.     private String accessKey;
  13.     private String secretKey;
  14.     private String bucket;
  15. }

 

三、上传配置类

WebFileUploadConfig.java

  1. package com.liuyanzhao.forum.config;
  2. import com.google.gson.Gson;
  3. import com.liuyanzhao.forum.vo.QiNiuProperties;
  4. import com.qiniu.common.Zone;
  5. import com.qiniu.storage.BucketManager;
  6. import com.qiniu.storage.UploadManager;
  7. import com.qiniu.util.Auth;
  8. import org.springframework.beans.factory.annotation.Autowired;
  9. import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
  10. import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
  11. import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
  12. import org.springframework.boot.autoconfigure.web.servlet.MultipartProperties;
  13. import org.springframework.boot.context.properties.EnableConfigurationProperties;
  14. import org.springframework.context.annotation.Bean;
  15. import org.springframework.context.annotation.Configuration;
  16. import org.springframework.web.multipart.MultipartResolver;
  17. import org.springframework.web.multipart.support.StandardServletMultipartResolver;
  18. import org.springframework.web.servlet.DispatcherServlet;
  19. import javax.servlet.MultipartConfigElement;
  20. import javax.servlet.Servlet;
  21. /**
  22.  * @author 言曌
  23.  * @date 2018/4/5 下午9:33
  24.  */
  25. @Configuration
  26. @ConditionalOnClass({Servlet.class, StandardServletMultipartResolver.class, MultipartConfigElement.class})
  27. @ConditionalOnProperty(prefix = "spring.servlet.multipart", name = "enabled", matchIfMissing = true)
  28. @EnableConfigurationProperties(MultipartProperties.class)
  29. public class WebFileUploadConfig {
  30.     /**
  31.      * 七牛云配置
  32.      */
  33.     @Autowired
  34.     private QiNiuProperties qiNiuProperties;
  35.     private final MultipartProperties multipartProperties;
  36.     public WebFileUploadConfig(MultipartProperties multipartProperties) {
  37.         this.multipartProperties = multipartProperties;
  38.     }
  39.     /**
  40.      * 上传配置
  41.      */
  42.     @Bean
  43.     @ConditionalOnMissingBean
  44.     public MultipartConfigElement multipartConfigElement() {
  45.         return this.multipartProperties.createMultipartConfig();
  46.     }
  47.     /**
  48.      * 注册解析器
  49.      */
  50.     @Bean(name = DispatcherServlet.MULTIPART_RESOLVER_BEAN_NAME)
  51.     @ConditionalOnMissingBean(MultipartResolver.class)
  52.     public StandardServletMultipartResolver multipartResolver() {
  53.         StandardServletMultipartResolver multipartResolver = new StandardServletMultipartResolver();
  54.         multipartResolver.setResolveLazily(this.multipartProperties.isResolveLazily());
  55.         return multipartResolver;
  56.     }
  57.     /**
  58.      * 华东   Zone.zone0()
  59.      * 华北   Zone.zone1()
  60.      * 华南   Zone.zone2()
  61.      * 北美   Zone.zoneNa0()
  62.      */
  63.     @Bean
  64.     public com.qiniu.storage.Configuration qiniuConfig() {
  65.         //华东
  66.         return new com.qiniu.storage.Configuration(Zone.zone0());
  67.     }
  68.     /**
  69.      * 构建一个七牛上传工具实例
  70.      */
  71.     @Bean
  72.     public UploadManager uploadManager() {
  73.         return new UploadManager(qiniuConfig());
  74.     }
  75.     /**
  76.      * 认证信息实例
  77.      *
  78.      * @return
  79.      */
  80.     @Bean
  81.     public Auth auth() {
  82.         return Auth.create(qiNiuProperties.getAccessKey(),
  83.                 qiNiuProperties.getSecretKey());
  84.     }
  85.     /**
  86.      * 构建七牛空间管理实例
  87.      */
  88.     @Bean
  89.     public BucketManager bucketManager() {
  90.         return new BucketManager(auth(), qiniuConfig());
  91.     }
  92.     /**
  93.      * 配置gson为json解析工具
  94.      *
  95.      * @return
  96.      */
  97.     @Bean
  98.     public Gson gson() {
  99.         return new Gson();
  100.     }
  101. }

 

四、上传 Service

QiNiuService.java

  1. package com.liuyanzhao.forum.service;
  2. import com.qiniu.common.QiniuException;
  3. import com.qiniu.http.Response;
  4. import java.io.File;
  5. import java.io.InputStream;
  6. /**
  7.  * @author 言曌
  8.  * @date 2018/4/5 下午9:38
  9.  */
  10. public interface QiNiuService {
  11.     /**
  12.      * 上传文件
  13.      * <p>
  14.      * (文件上传)
  15.      *
  16.      * @param file
  17.      * @return
  18.      * @throws QiniuException
  19.      */
  20.     Response uploadFile(File file) throws QiniuException;
  21.     /**
  22.      * 上传文件
  23.      * <p>
  24.      * (文件流上传)
  25.      *
  26.      * @param inputStream
  27.      * @return
  28.      * @throws QiniuException
  29.      */
  30.     Response uploadFile(InputStream inputStream) throws QiniuException;
  31.     /**
  32.      * 删除
  33.      *
  34.      * @param key
  35.      * @return
  36.      * @throws QiniuException
  37.      */
  38.     Response delete(String key) throws QiniuException;
  39. }

 

QiNiuServiceImpl.java

  1. package com.liuyanzhao.forum.service.impl;
  2. import com.liuyanzhao.forum.service.QiNiuService;
  3. import com.liuyanzhao.forum.vo.QiNiuProperties;
  4. import com.qiniu.common.QiniuException;
  5. import com.qiniu.http.Response;
  6. import com.qiniu.storage.BucketManager;
  7. import com.qiniu.storage.UploadManager;
  8. import com.qiniu.util.Auth;
  9. import com.qiniu.util.StringMap;
  10. import org.springframework.beans.factory.InitializingBean;
  11. import org.springframework.beans.factory.annotation.Autowired;
  12. import org.springframework.stereotype.Service;
  13. import java.io.File;
  14. import java.io.InputStream;
  15. /**
  16.  * @author 言曌
  17.  * @date 2018/4/5 下午9:39
  18.  */
  19. @Service
  20. public class QiNiuServiceImpl implements QiNiuService, InitializingBean {
  21.     @Autowired
  22.     private UploadManager uploadManager;
  23.     @Autowired
  24.     private BucketManager bucketManager;
  25.     @Autowired
  26.     private Auth auth;
  27.     @Autowired
  28.     private QiNiuProperties qiNiuProperties;
  29.     private StringMap putPolicy;
  30.     @Override
  31.     public Response uploadFile(File file) throws QiniuException {
  32.         Response response = this.uploadManager.put(file, null, getUploadToken());
  33.         int retry = 0;
  34.         while (response.needRetry() && retry < 3) {
  35.             response = this.uploadManager.put(file, null, getUploadToken());
  36.             retry++;
  37.         }
  38.         return response;
  39.     }
  40.     @Override
  41.     public Response uploadFile(InputStream inputStream) throws QiniuException {
  42.         Response response = this.uploadManager.put(inputStream, null, getUploadToken(), nullnull);
  43.         int retry = 0;
  44.         while (response.needRetry() && retry < 3) {
  45.             response = this.uploadManager.put(inputStream, null, getUploadToken(), nullnull);
  46.             retry++;
  47.         }
  48.         return response;
  49.     }
  50.     @Override
  51.     public Response delete(String key) throws QiniuException {
  52.         Response response = bucketManager.delete(qiNiuProperties.getBucket(), key);
  53.         int retry = 0;
  54.         while (response.needRetry() && retry++ < 3) {
  55.             response = bucketManager.delete(qiNiuProperties.getBucket(), key);
  56.         }
  57.         return response;
  58.     }
  59.     @Override
  60.     public void afterPropertiesSet() throws Exception {
  61.         this.putPolicy = new StringMap();
  62.         putPolicy.put("returnBody""{\"key\":\"$(key)\",\"hash\":\"$(etag)\",\"bucket\":\"$(bucket)\",\"width\":$(imageInfo.width), \"height\":${imageInfo.height}}");
  63.     }
  64.     /**
  65.      * 获取上传凭证
  66.      *
  67.      * @return
  68.      */
  69.     private String getUploadToken() {
  70.         return this.auth.uploadToken(qiNiuProperties.getBucket(), null3600, putPolicy);
  71.     }
  72. }

 

五、测试上传

QiNiuServiceImplTest.java

  1. @SpringBootTest
  2. @RunWith(SpringRunner.class)
  3. public class QiNiuServiceImplTest {
  4.     @Autowired
  5.     private QiNiuServiceImpl qiNiuService;
  6.     @Test
  7.     public void uploadFile() throws QiniuException {
  8.         String fileName = "/Users/liuyanzhao/Desktop/avatar.jpg";
  9.         File file = new File(fileName);
  10.         assertTrue(file.exists());
  11.         Response response = qiNiuService.uploadFile(file);
  12.         assertTrue(response.isOK());
  13.         //解析上传成功的结果
  14.         DefaultPutRet putRet = new Gson().fromJson(response.bodyString(), DefaultPutRet.class);
  15.         System.out.println(putRet.key);//根据 http://域名/key 就能访问文件
  16.     }
  17. }

 

系统会根据图片的哈希值来判断是否是重复的图片,比如我上传过那张 avatar.jpg,过一段时间又上传一次,七牛云服务器不会重新上传,直接返回原来那张图片的软链接。

 

我们运行测试类

控制台没有报错,输出 FkEQ5f2qvLYAheAsKJ3qExrHM19L,这个key就是文件名

然后我们去存储空间看一下,果然有这个文件

spring boot使用七牛云做文件上传并返回图片地址

图片的外链:http://域名/key

比如,我们这里有两个域名,下面那个是七牛云给的,而那个 coder.liuyanzhao.com 是自定义域名,需要绑定。

spring boot使用七牛云做文件上传并返回图片地址

 

我们通过这两个域名都能访问到我们上传的文件

http://p6pteljf0.bkt.clouddn.com/FkEQ5f2qvLYAheAsKJ3qExrHM19L

http://coder.liuyanzhao.com/FkEQ5f2qvLYAheAsKJ3qExrHM19L

 

 

参考

七牛云官方文档

spring boot使用七牛云的oss(对象存储)文件上传

 

 

本文地址: https://liuyanzhao.com/7937.html

  • 微信
  • 赶快加我聊天吧
  • weinxin
  • 博客/Java交流群
  • 资源分享,问题解决,技术交流。群号:590480292
  • weinxin
广告也精彩
言曌
广告也精彩

发表评论

:?::razz::sad::evil::!::smile::oops::grin::eek::shock::???::cool::lol::mad::twisted::roll::wink::idea::arrow::neutral::cry::mrgreen: