@@ -38,3 +38,5 @@ logs/ | |||||
### VS CODE ### | ### VS CODE ### | ||||
.vscode/ | .vscode/ | ||||
tmp/ |
@@ -1,25 +0,0 @@ | |||||
/target/ | |||||
!.mvn/wrapper/maven-wrapper.jar | |||||
### STS ### | |||||
.apt_generated | |||||
.classpath | |||||
.factorypath | |||||
.project | |||||
.settings | |||||
.springBeans | |||||
.sts4-cache | |||||
### IntelliJ IDEA ### | |||||
.idea | |||||
*.iws | |||||
*.iml | |||||
*.ipr | |||||
### NetBeans ### | |||||
/nbproject/private/ | |||||
/build/ | |||||
/nbbuild/ | |||||
/dist/ | |||||
/nbdist/ | |||||
/.nb-gradle/ |
@@ -2,503 +2,202 @@ | |||||
> 本 demo 演示了 Spring Boot 如何实现本地文件上传以及如何上传文件至七牛云平台。前端使用 vue 和 iview 实现上传页面。 | > 本 demo 演示了 Spring Boot 如何实现本地文件上传以及如何上传文件至七牛云平台。前端使用 vue 和 iview 实现上传页面。 | ||||
## pom.xml | |||||
## 1.开发步骤 | |||||
### 1.1.添加依赖 | |||||
```xml | ```xml | ||||
<?xml version="1.0" encoding="UTF-8"?> | |||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | |||||
<modelVersion>4.0.0</modelVersion> | |||||
<artifactId>spring-boot-demo-upload</artifactId> | |||||
<version>1.0.0-SNAPSHOT</version> | |||||
<packaging>jar</packaging> | |||||
<name>spring-boot-demo-upload</name> | |||||
<description>Demo project for Spring Boot</description> | |||||
<parent> | |||||
<groupId>com.xkcoding</groupId> | |||||
<artifactId>spring-boot-demo</artifactId> | |||||
<version>1.0.0-SNAPSHOT</version> | |||||
</parent> | |||||
<properties> | |||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> | |||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> | |||||
<java.version>1.8</java.version> | |||||
</properties> | |||||
<dependencies> | |||||
<dependency> | |||||
<groupId>org.projectlombok</groupId> | |||||
<artifactId>lombok</artifactId> | |||||
<optional>true</optional> | |||||
</dependency> | |||||
<dependency> | |||||
<groupId>org.springframework.boot</groupId> | |||||
<artifactId>spring-boot-starter-web</artifactId> | |||||
</dependency> | |||||
<dependency> | |||||
<groupId>org.springframework.boot</groupId> | |||||
<artifactId>spring-boot-starter-thymeleaf</artifactId> | |||||
</dependency> | |||||
<dependency> | |||||
<groupId>org.springframework.boot</groupId> | |||||
<artifactId>spring-boot-starter-test</artifactId> | |||||
<scope>test</scope> | |||||
</dependency> | |||||
<dependency> | |||||
<groupId>cn.hutool</groupId> | |||||
<artifactId>hutool-all</artifactId> | |||||
</dependency> | |||||
<dependency> | |||||
<groupId>com.qiniu</groupId> | |||||
<artifactId>qiniu-java-sdk</artifactId> | |||||
<version>[7.2.0, 7.2.99]</version> | |||||
</dependency> | |||||
</dependencies> | |||||
<build> | |||||
<finalName>spring-boot-demo-upload</finalName> | |||||
<plugins> | |||||
<plugin> | |||||
<groupId>org.springframework.boot</groupId> | |||||
<artifactId>spring-boot-maven-plugin</artifactId> | |||||
</plugin> | |||||
</plugins> | |||||
</build> | |||||
</project> | |||||
<dependencies> | |||||
<dependency> | |||||
<groupId>com.xkcoding</groupId> | |||||
<artifactId>common-tools</artifactId> | |||||
</dependency> | |||||
<dependency> | |||||
<groupId>org.springframework.boot</groupId> | |||||
<artifactId>spring-boot-starter-web</artifactId> | |||||
</dependency> | |||||
<dependency> | |||||
<groupId>org.springframework.boot</groupId> | |||||
<artifactId>spring-boot-starter-thymeleaf</artifactId> | |||||
</dependency> | |||||
<dependency> | |||||
<groupId>org.springframework.boot</groupId> | |||||
<artifactId>spring-boot-starter-test</artifactId> | |||||
<scope>test</scope> | |||||
</dependency> | |||||
<dependency> | |||||
<groupId>com.qiniu</groupId> | |||||
<artifactId>qiniu-java-sdk</artifactId> | |||||
<version>${qiniu.version}</version> | |||||
</dependency> | |||||
<!-- 七牛云 sdk 必须需要 okhttp 客户端 --> | |||||
<dependency> | |||||
<groupId>com.squareup.okhttp3</groupId> | |||||
<artifactId>okhttp</artifactId> | |||||
<version>3.14.4</version> | |||||
</dependency> | |||||
<dependency> | |||||
<groupId>org.projectlombok</groupId> | |||||
<artifactId>lombok</artifactId> | |||||
<optional>true</optional> | |||||
</dependency> | |||||
</dependencies> | |||||
``` | ``` | ||||
## UploadConfig.java | |||||
### 1.2.七牛云配置类 | |||||
```java | ```java | ||||
/** | |||||
* <p> | |||||
* 上传配置 | |||||
* </p> | |||||
* | |||||
* @author yangkai.shen | |||||
* @date Created in 2018-10-23 14:09 | |||||
*/ | |||||
@Configuration | |||||
@ConditionalOnClass({Servlet.class, StandardServletMultipartResolver.class, MultipartConfigElement.class}) | |||||
@ConditionalOnProperty(prefix = "spring.http.multipart", name = "enabled", matchIfMissing = true) | |||||
@EnableConfigurationProperties(MultipartProperties.class) | |||||
public class UploadConfig { | |||||
@Value("${qiniu.accessKey}") | |||||
private String accessKey; | |||||
@Value("${qiniu.secretKey}") | |||||
private String secretKey; | |||||
private final MultipartProperties multipartProperties; | |||||
@Autowired | |||||
public UploadConfig(MultipartProperties multipartProperties) { | |||||
this.multipartProperties = multipartProperties; | |||||
} | |||||
/** | |||||
* 上传配置 | |||||
*/ | |||||
@Bean | |||||
@ConditionalOnMissingBean | |||||
public MultipartConfigElement multipartConfigElement() { | |||||
return this.multipartProperties.createMultipartConfig(); | |||||
} | |||||
/** | |||||
* 注册解析器 | |||||
*/ | |||||
@Bean(name = DispatcherServlet.MULTIPART_RESOLVER_BEAN_NAME) | |||||
@ConditionalOnMissingBean(MultipartResolver.class) | |||||
public StandardServletMultipartResolver multipartResolver() { | |||||
StandardServletMultipartResolver multipartResolver = new StandardServletMultipartResolver(); | |||||
multipartResolver.setResolveLazily(this.multipartProperties.isResolveLazily()); | |||||
return multipartResolver; | |||||
} | |||||
/** | |||||
* 华东机房 | |||||
*/ | |||||
@Bean | |||||
public com.qiniu.storage.Configuration qiniuConfig() { | |||||
return new com.qiniu.storage.Configuration(Zone.zone0()); | |||||
} | |||||
/** | |||||
* 构建一个七牛上传工具实例 | |||||
*/ | |||||
@Bean | |||||
public UploadManager uploadManager() { | |||||
return new UploadManager(qiniuConfig()); | |||||
} | |||||
/** | |||||
* 认证信息实例 | |||||
*/ | |||||
@Bean | |||||
public Auth auth() { | |||||
return Auth.create(accessKey, secretKey); | |||||
} | |||||
/** | |||||
* 构建七牛空间管理实例 | |||||
*/ | |||||
@Bean | |||||
public BucketManager bucketManager() { | |||||
return new BucketManager(auth(), qiniuConfig()); | |||||
} | |||||
@Data | |||||
@ConfigurationProperties(prefix = "qiniu") | |||||
public class QiniuProperties { | |||||
private String accessKey; | |||||
private String secretKey; | |||||
private String bucket; | |||||
private String prefix; | |||||
} | } | ||||
``` | ``` | ||||
## UploadController.java | |||||
### 1.3.自动装配类 | |||||
```java | ```java | ||||
/** | |||||
* <p> | |||||
* 文件上传 Controller | |||||
* </p> | |||||
* | |||||
* @author yangkai.shen | |||||
* @date Created in 2018-11-06 16:33 | |||||
*/ | |||||
@RestController | |||||
@Slf4j | |||||
@RequestMapping("/upload") | |||||
public class UploadController { | |||||
@Value("${spring.servlet.multipart.location}") | |||||
private String fileTempPath; | |||||
@Value("${qiniu.prefix}") | |||||
private String prefix; | |||||
private final IQiNiuService qiNiuService; | |||||
@Autowired | |||||
public UploadController(IQiNiuService qiNiuService) { | |||||
this.qiNiuService = qiNiuService; | |||||
} | |||||
@PostMapping(value = "/local", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) | |||||
public Dict local(@RequestParam("file") MultipartFile file) { | |||||
if (file.isEmpty()) { | |||||
return Dict.create().set("code", 400).set("message", "文件内容为空"); | |||||
} | |||||
String fileName = file.getOriginalFilename(); | |||||
String rawFileName = StrUtil.subBefore(fileName, ".", true); | |||||
String fileType = StrUtil.subAfter(fileName, ".", true); | |||||
String localFilePath = StrUtil.appendIfMissing(fileTempPath, "/") + rawFileName + "-" + DateUtil.current(false) + "." + fileType; | |||||
try { | |||||
file.transferTo(new File(localFilePath)); | |||||
} catch (IOException e) { | |||||
log.error("【文件上传至本地】失败,绝对路径:{}", localFilePath); | |||||
return Dict.create().set("code", 500).set("message", "文件上传失败"); | |||||
} | |||||
log.info("【文件上传至本地】绝对路径:{}", localFilePath); | |||||
return Dict.create().set("code", 200).set("message", "上传成功").set("data", Dict.create().set("fileName", fileName).set("filePath", localFilePath)); | |||||
} | |||||
@PostMapping(value = "/yun", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) | |||||
public Dict yun(@RequestParam("file") MultipartFile file) { | |||||
if (file.isEmpty()) { | |||||
return Dict.create().set("code", 400).set("message", "文件内容为空"); | |||||
} | |||||
String fileName = file.getOriginalFilename(); | |||||
String rawFileName = StrUtil.subBefore(fileName, ".", true); | |||||
String fileType = StrUtil.subAfter(fileName, ".", true); | |||||
String localFilePath = StrUtil.appendIfMissing(fileTempPath, "/") + rawFileName + "-" + DateUtil.current(false) + "." + fileType; | |||||
try { | |||||
file.transferTo(new File(localFilePath)); | |||||
Response response = qiNiuService.uploadFile(new File(localFilePath)); | |||||
if (response.isOK()) { | |||||
JSONObject jsonObject = JSONUtil.parseObj(response.bodyString()); | |||||
String yunFileName = jsonObject.getStr("key"); | |||||
String yunFilePath = StrUtil.appendIfMissing(prefix, "/") + yunFileName; | |||||
FileUtil.del(new File(localFilePath)); | |||||
log.info("【文件上传至七牛云】绝对路径:{}", yunFilePath); | |||||
return Dict.create().set("code", 200).set("message", "上传成功").set("data", Dict.create().set("fileName", yunFileName).set("filePath", yunFilePath)); | |||||
} else { | |||||
log.error("【文件上传至七牛云】失败,{}", JSONUtil.toJsonStr(response)); | |||||
FileUtil.del(new File(localFilePath)); | |||||
return Dict.create().set("code", 500).set("message", "文件上传失败"); | |||||
} | |||||
} catch (IOException e) { | |||||
log.error("【文件上传至七牛云】失败,绝对路径:{}", localFilePath); | |||||
return Dict.create().set("code", 500).set("message", "文件上传失败"); | |||||
} | |||||
} | |||||
@Configuration | |||||
@ConditionalOnClass({Servlet.class, StandardServletMultipartResolver.class, MultipartConfigElement.class}) | |||||
@ConditionalOnProperty(prefix = "spring.http.multipart", name = "enabled", matchIfMissing = true) | |||||
@EnableConfigurationProperties({MultipartProperties.class, QiniuProperties.class}) | |||||
@RequiredArgsConstructor(onConstructor_ = @Autowired) | |||||
public class UploadAutoConfiguration { | |||||
private final MultipartProperties multipartProperties; | |||||
private final QiniuProperties qiniuProperties; | |||||
/** | |||||
* 上传配置 | |||||
*/ | |||||
@Bean | |||||
@ConditionalOnMissingBean | |||||
public MultipartConfigElement multipartConfigElement() { | |||||
return this.multipartProperties.createMultipartConfig(); | |||||
} | |||||
/** | |||||
* 注册解析器 | |||||
*/ | |||||
@Bean(name = DispatcherServlet.MULTIPART_RESOLVER_BEAN_NAME) | |||||
@ConditionalOnMissingBean(MultipartResolver.class) | |||||
public StandardServletMultipartResolver multipartResolver() { | |||||
StandardServletMultipartResolver multipartResolver = new StandardServletMultipartResolver(); | |||||
multipartResolver.setResolveLazily(this.multipartProperties.isResolveLazily()); | |||||
return multipartResolver; | |||||
} | |||||
/** | |||||
* 华东机房 | |||||
*/ | |||||
@Bean | |||||
public com.qiniu.storage.Configuration qiniuConfig() { | |||||
return new com.qiniu.storage.Configuration(Region.region0()); | |||||
} | |||||
/** | |||||
* 构建一个七牛上传工具实例 | |||||
*/ | |||||
@Bean | |||||
public UploadManager uploadManager() { | |||||
return new UploadManager(qiniuConfig()); | |||||
} | |||||
/** | |||||
* 认证信息实例 | |||||
*/ | |||||
@Bean | |||||
public Auth auth() { | |||||
return Auth.create(qiniuProperties.getAccessKey(), qiniuProperties.getSecretKey()); | |||||
} | |||||
/** | |||||
* 构建七牛空间管理实例 | |||||
*/ | |||||
@Bean | |||||
public BucketManager bucketManager() { | |||||
return new BucketManager(auth(), qiniuConfig()); | |||||
} | |||||
} | } | ||||
``` | ``` | ||||
## QiNiuServiceImpl.java | |||||
### 1.4.七牛云上传代码 | |||||
```java | ```java | ||||
/** | |||||
* <p> | |||||
* 七牛云上传Service | |||||
* </p> | |||||
* | |||||
* @author yangkai.shen | |||||
* @date Created in 2018-11-06 17:22 | |||||
*/ | |||||
@Service | |||||
@Slf4j | @Slf4j | ||||
public class QiNiuServiceImpl implements IQiNiuService, InitializingBean { | |||||
private final UploadManager uploadManager; | |||||
private final Auth auth; | |||||
@Value("${qiniu.bucket}") | |||||
private String bucket; | |||||
private StringMap putPolicy; | |||||
@Autowired | |||||
public QiNiuServiceImpl(UploadManager uploadManager, Auth auth) { | |||||
this.uploadManager = uploadManager; | |||||
this.auth = auth; | |||||
} | |||||
/** | |||||
* 七牛云上传文件 | |||||
* | |||||
* @param file 文件 | |||||
* @return 七牛上传Response | |||||
* @throws QiniuException 七牛异常 | |||||
*/ | |||||
@Override | |||||
public Response uploadFile(File file) throws QiniuException { | |||||
Response response = this.uploadManager.put(file, file.getName(), getUploadToken()); | |||||
int retry = 0; | |||||
while (response.needRetry() && retry < 3) { | |||||
response = this.uploadManager.put(file, file.getName(), getUploadToken()); | |||||
retry++; | |||||
} | |||||
return response; | |||||
} | |||||
@Override | |||||
public void afterPropertiesSet() { | |||||
this.putPolicy = new StringMap(); | |||||
putPolicy.put("returnBody", "{\"key\":\"$(key)\",\"hash\":\"$(etag)\",\"bucket\":\"$(bucket)\",\"width\":$(imageInfo.width), \"height\":${imageInfo.height}}"); | |||||
} | |||||
/** | |||||
* 获取上传凭证 | |||||
* | |||||
* @return 上传凭证 | |||||
*/ | |||||
private String getUploadToken() { | |||||
return this.auth.uploadToken(bucket, null, 3600, putPolicy); | |||||
} | |||||
@Service | |||||
@RequiredArgsConstructor(onConstructor_ = @Autowired) | |||||
public class QiNiuService implements InitializingBean { | |||||
private final Auth auth; | |||||
private final UploadManager uploadManager; | |||||
private final QiniuProperties qiniuProperties; | |||||
private StringMap putPolicy; | |||||
/** | |||||
* 七牛云上传文件 | |||||
* | |||||
* @param file 文件 | |||||
* @return 七牛上传Response | |||||
* @throws QiniuException 七牛异常 | |||||
*/ | |||||
public Response uploadFile(File file) throws QiniuException { | |||||
Response response = this.uploadManager.put(file, file.getName(), getUploadToken()); | |||||
int retry = 0; | |||||
while (response.needRetry() && retry < 3) { | |||||
response = this.uploadManager.put(file, file.getName(), getUploadToken()); | |||||
retry++; | |||||
} | |||||
return response; | |||||
} | |||||
@Override | |||||
public void afterPropertiesSet() { | |||||
this.putPolicy = new StringMap(); | |||||
putPolicy.put("returnBody", | |||||
"{\"key\":\"$(key)\",\"hash\":\"$(etag)\",\"bucket\":\"$(bucket)\",\"width\":$(imageInfo.width), \"height\":${imageInfo.height}}"); | |||||
} | |||||
/** | |||||
* 获取上传凭证 | |||||
* | |||||
* @return 上传凭证 | |||||
*/ | |||||
private String getUploadToken() { | |||||
return this.auth.uploadToken(qiniuProperties.getBucket(), null, 3600, putPolicy); | |||||
} | |||||
} | } | ||||
``` | ``` | ||||
## index.html | |||||
```html | |||||
<!doctype html> | |||||
<html lang="en"> | |||||
<head> | |||||
<meta charset="UTF-8"> | |||||
<meta name="viewport" | |||||
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> | |||||
<meta http-equiv="X-UA-Compatible" content="ie=edge"> | |||||
<title>spring-boot-demo-upload</title> | |||||
<!-- import Vue.js --> | |||||
<script src="https://cdn.bootcss.com/vue/2.5.17/vue.min.js"></script> | |||||
<!-- import stylesheet --> | |||||
<link href="https://cdn.bootcss.com/iview/3.1.4/styles/iview.css" rel="stylesheet"> | |||||
<!-- import iView --> | |||||
<script src="https://cdn.bootcss.com/iview/3.1.4/iview.min.js"></script> | |||||
</head> | |||||
<body> | |||||
<div id="app"> | |||||
<Row :gutter="16" style="background:#eee;padding:10%"> | |||||
<i-col span="12"> | |||||
<Card style="height: 300px"> | |||||
<p slot="title"> | |||||
<Icon type="ios-cloud-upload"></Icon> | |||||
本地上传 | |||||
</p> | |||||
<div style="text-align: center;"> | |||||
<Upload | |||||
:before-upload="handleLocalUpload" | |||||
action="/demo/upload/local" | |||||
ref="localUploadRef" | |||||
:on-success="handleLocalSuccess" | |||||
:on-error="handleLocalError" | |||||
> | |||||
<i-button icon="ios-cloud-upload-outline">选择文件</i-button> | |||||
</Upload> | |||||
<i-button | |||||
type="primary" | |||||
@click="localUpload" | |||||
:loading="local.loadingStatus" | |||||
:disabled="!local.file"> | |||||
{{ local.loadingStatus ? '本地文件上传中' : '本地上传' }} | |||||
</i-button> | |||||
</div> | |||||
<div> | |||||
<div v-if="local.log.status != 0">状态:{{local.log.message}}</div> | |||||
<div v-if="local.log.status === 200">文件名:{{local.log.fileName}}</div> | |||||
<div v-if="local.log.status === 200">文件路径:{{local.log.filePath}}</div> | |||||
</div> | |||||
</Card> | |||||
</i-col> | |||||
<i-col span="12"> | |||||
<Card style="height: 300px;"> | |||||
<p slot="title"> | |||||
<Icon type="md-cloud-upload"></Icon> | |||||
七牛云上传 | |||||
</p> | |||||
<div style="text-align: center;"> | |||||
<Upload | |||||
:before-upload="handleYunUpload" | |||||
action="/demo/upload/yun" | |||||
ref="yunUploadRef" | |||||
:on-success="handleYunSuccess" | |||||
:on-error="handleYunError" | |||||
> | |||||
<i-button icon="ios-cloud-upload-outline">选择文件</i-button> | |||||
</Upload> | |||||
<i-button | |||||
type="primary" | |||||
@click="yunUpload" | |||||
:loading="yun.loadingStatus" | |||||
:disabled="!yun.file"> | |||||
{{ yun.loadingStatus ? '七牛云文件上传中' : '七牛云上传' }} | |||||
</i-button> | |||||
</div> | |||||
<div> | |||||
<div v-if="yun.log.status != 0">状态:{{yun.log.message}}</div> | |||||
<div v-if="yun.log.status === 200">文件名:{{yun.log.fileName}}</div> | |||||
<div v-if="yun.log.status === 200">文件路径:{{yun.log.filePath}}</div> | |||||
</div> | |||||
</Card> | |||||
</i-col> | |||||
</Row> | |||||
</div> | |||||
<script> | |||||
new Vue({ | |||||
el: '#app', | |||||
data: { | |||||
local: { | |||||
// 选择文件后,将 beforeUpload 返回的 file 保存在这里,后面会用到 | |||||
file: null, | |||||
// 标记上传状态 | |||||
loadingStatus: false, | |||||
log: { | |||||
status: 0, | |||||
message: "", | |||||
fileName: "", | |||||
filePath: "" | |||||
} | |||||
}, | |||||
yun: { | |||||
// 选择文件后,将 beforeUpload 返回的 file 保存在这里,后面会用到 | |||||
file: null, | |||||
// 标记上传状态 | |||||
loadingStatus: false, | |||||
log: { | |||||
status: 0, | |||||
message: "", | |||||
fileName: "", | |||||
filePath: "" | |||||
} | |||||
} | |||||
}, | |||||
methods: { | |||||
// beforeUpload 在返回 false 或 Promise 时,会停止自动上传,这里我们将选择好的文件 file 保存在 data里,并 return false | |||||
handleLocalUpload(file) { | |||||
this.local.file = file; | |||||
return false; | |||||
}, | |||||
// 这里是手动上传,通过 $refs 获取到 Upload 实例,然后调用私有方法 .post(),把保存在 data 里的 file 上传。 | |||||
// iView 的 Upload 组件在调用 .post() 方法时,就会继续上传了。 | |||||
localUpload() { | |||||
this.local.loadingStatus = true; // 标记上传状态 | |||||
this.$refs.localUploadRef.post(this.local.file); | |||||
}, | |||||
// 上传成功后,清空 data 里的 file,并修改上传状态 | |||||
handleLocalSuccess(response) { | |||||
this.local.file = null; | |||||
this.local.loadingStatus = false; | |||||
if (response.code === 200) { | |||||
this.$Message.success(response.message); | |||||
this.local.log.status = response.code; | |||||
this.local.log.message = response.message; | |||||
this.local.log.fileName = response.data.fileName; | |||||
this.local.log.filePath = response.data.filePath; | |||||
this.$refs.localUploadRef.clearFiles(); | |||||
} else { | |||||
this.$Message.error(response.message); | |||||
this.local.log.status = response.code; | |||||
this.local.log.message = response.message; | |||||
} | |||||
}, | |||||
// 上传失败后,清空 data 里的 file,并修改上传状态 | |||||
handleLocalError() { | |||||
this.local.file = null; | |||||
this.local.loadingStatus = false; | |||||
this.$Message.error('上传失败'); | |||||
}, | |||||
// beforeUpload 在返回 false 或 Promise 时,会停止自动上传,这里我们将选择好的文件 file 保存在 data里,并 return false | |||||
handleYunUpload(file) { | |||||
this.yun.file = file; | |||||
return false; | |||||
}, | |||||
// 这里是手动上传,通过 $refs 获取到 Upload 实例,然后调用私有方法 .post(),把保存在 data 里的 file 上传。 | |||||
// iView 的 Upload 组件在调用 .post() 方法时,就会继续上传了。 | |||||
yunUpload() { | |||||
this.yun.loadingStatus = true; // 标记上传状态 | |||||
this.$refs.yunUploadRef.post(this.yun.file); | |||||
}, | |||||
// 上传成功后,清空 data 里的 file,并修改上传状态 | |||||
handleYunSuccess(response) { | |||||
this.yun.file = null; | |||||
this.yun.loadingStatus = false; | |||||
if (response.code === 200) { | |||||
this.$Message.success(response.message); | |||||
this.yun.log.status = response.code; | |||||
this.yun.log.message = response.message; | |||||
this.yun.log.fileName = response.data.fileName; | |||||
this.yun.log.filePath = response.data.filePath; | |||||
this.$refs.yunUploadRef.clearFiles(); | |||||
} else { | |||||
this.$Message.error(response.message); | |||||
this.yun.log.status = response.code; | |||||
this.yun.log.message = response.message; | |||||
} | |||||
}, | |||||
// 上传失败后,清空 data 里的 file,并修改上传状态 | |||||
handleYunError() { | |||||
this.yun.file = null; | |||||
this.yun.loadingStatus = false; | |||||
this.$Message.error('上传失败'); | |||||
} | |||||
} | |||||
}) | |||||
</script> | |||||
</body> | |||||
</html> | |||||
``` | |||||
### 1.5.测试Controller及前端页面 | |||||
> 不是专业前端,就不在 README 献丑了,代码直接参考 `resources/templates/index.html` 即可 | |||||
## 2.测试 | |||||
> 注意:测试七牛云时,需要先在 `application.yml` 中配置 `qiniu.xxx` 相关参数 | |||||
启动 `UploadApplication` ,打开浏览器,输入 http://localhost:8080/demo | |||||
上传几张图片试试~ | |||||
 | |||||
## 3.参考 | |||||
- [Spring Boot 官方文档之文件上传](https://docs.spring.io/spring-boot/docs/3.0.0-M4/reference/htmlsingle/#howto.spring-mvc.multipart-file-uploads) | |||||
## 参考 | |||||
- [七牛云官方文档之 Java SDK](https://developer.qiniu.com/kodo/1239/java) | |||||
1. Spring 官方文档:https://docs.spring.io/spring-boot/docs/2.1.0.RELEASE/reference/htmlsingle/#howto-multipart-file-upload-configuration | |||||
2. 七牛云官方文档:https://developer.qiniu.com/kodo/sdk/1239/java#5 | |||||
## 4.特别感谢 | |||||
- 感谢 [七牛云](https://portal.qiniu.com/signup?utm_source=kaiyuan&utm_media=xkcoding) 提供的免费云存储与 CDN 加速支持 |
@@ -1,70 +1,77 @@ | |||||
<?xml version="1.0" encoding="UTF-8"?> | <?xml version="1.0" encoding="UTF-8"?> | ||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||||
<modelVersion>4.0.0</modelVersion> | |||||
<artifactId>demo-upload</artifactId> | |||||
<parent> | |||||
<groupId>com.xkcoding</groupId> | |||||
<artifactId>demo-base</artifactId> | |||||
<version>1.0.0-SNAPSHOT</version> | <version>1.0.0-SNAPSHOT</version> | ||||
<packaging>jar</packaging> | |||||
</parent> | |||||
<modelVersion>4.0.0</modelVersion> | |||||
<artifactId>demo-base-upload</artifactId> | |||||
<version>1.0.0-SNAPSHOT</version> | |||||
<packaging>jar</packaging> | |||||
<name>demo-base-upload</name> | |||||
<description>Demo project for Spring Boot</description> | |||||
<name>demo-upload</name> | |||||
<description>Demo project for Spring Boot</description> | |||||
<properties> | |||||
<java.version>17</java.version> | |||||
<parent> | |||||
<groupId>com.xkcoding</groupId> | |||||
<artifactId>spring-boot-demo</artifactId> | |||||
<version>1.0.0-SNAPSHOT</version> | |||||
</parent> | |||||
<qiniu.version>7.11.0</qiniu.version> | |||||
</properties> | |||||
<properties> | |||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> | |||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> | |||||
<java.version>1.8</java.version> | |||||
</properties> | |||||
<dependencies> | |||||
<dependency> | |||||
<groupId>com.xkcoding</groupId> | |||||
<artifactId>common-tools</artifactId> | |||||
</dependency> | |||||
<dependencies> | |||||
<dependency> | |||||
<groupId>org.projectlombok</groupId> | |||||
<artifactId>lombok</artifactId> | |||||
<optional>true</optional> | |||||
</dependency> | |||||
<dependency> | |||||
<groupId>org.springframework.boot</groupId> | |||||
<artifactId>spring-boot-starter-web</artifactId> | |||||
</dependency> | |||||
<dependency> | |||||
<groupId>org.springframework.boot</groupId> | |||||
<artifactId>spring-boot-starter-web</artifactId> | |||||
</dependency> | |||||
<dependency> | |||||
<groupId>org.springframework.boot</groupId> | |||||
<artifactId>spring-boot-starter-thymeleaf</artifactId> | |||||
</dependency> | |||||
<dependency> | |||||
<groupId>org.springframework.boot</groupId> | |||||
<artifactId>spring-boot-starter-thymeleaf</artifactId> | |||||
</dependency> | |||||
<dependency> | |||||
<groupId>org.springframework.boot</groupId> | |||||
<artifactId>spring-boot-starter-test</artifactId> | |||||
<scope>test</scope> | |||||
</dependency> | |||||
<dependency> | |||||
<groupId>org.springframework.boot</groupId> | |||||
<artifactId>spring-boot-starter-test</artifactId> | |||||
<scope>test</scope> | |||||
</dependency> | |||||
<dependency> | |||||
<groupId>com.qiniu</groupId> | |||||
<artifactId>qiniu-java-sdk</artifactId> | |||||
<version>${qiniu.version}</version> | |||||
</dependency> | |||||
<dependency> | |||||
<groupId>cn.hutool</groupId> | |||||
<artifactId>hutool-all</artifactId> | |||||
</dependency> | |||||
<!-- 七牛云 sdk 必须需要 okhttp 客户端 --> | |||||
<dependency> | |||||
<groupId>com.squareup.okhttp3</groupId> | |||||
<artifactId>okhttp</artifactId> | |||||
<version>3.14.4</version> | |||||
</dependency> | |||||
<dependency> | |||||
<groupId>com.qiniu</groupId> | |||||
<artifactId>qiniu-java-sdk</artifactId> | |||||
<version>[7.2.0, 7.2.99]</version> | |||||
</dependency> | |||||
</dependencies> | |||||
<dependency> | |||||
<groupId>org.projectlombok</groupId> | |||||
<artifactId>lombok</artifactId> | |||||
<optional>true</optional> | |||||
</dependency> | |||||
</dependencies> | |||||
<build> | |||||
<finalName>demo-upload</finalName> | |||||
<plugins> | |||||
<plugin> | |||||
<groupId>org.springframework.boot</groupId> | |||||
<artifactId>spring-boot-maven-plugin</artifactId> | |||||
</plugin> | |||||
</plugins> | |||||
</build> | |||||
<build> | |||||
<finalName>demo-base-upload</finalName> | |||||
<plugins> | |||||
<plugin> | |||||
<groupId>org.springframework.boot</groupId> | |||||
<artifactId>spring-boot-maven-plugin</artifactId> | |||||
</plugin> | |||||
</plugins> | |||||
</build> | |||||
</project> | </project> |
@@ -12,9 +12,9 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; | |||||
* @date Created in 2018-10-20 21:23 | * @date Created in 2018-10-20 21:23 | ||||
*/ | */ | ||||
@SpringBootApplication | @SpringBootApplication | ||||
public class SpringBootDemoUploadApplication { | |||||
public class UploadApplication { | |||||
public static void main(String[] args) { | public static void main(String[] args) { | ||||
SpringApplication.run(SpringBootDemoUploadApplication.class, args); | |||||
SpringApplication.run(UploadApplication.class, args); | |||||
} | } | ||||
} | } |
@@ -0,0 +1,22 @@ | |||||
package com.xkcoding.upload.autoconfigure; | |||||
import lombok.Data; | |||||
import org.springframework.boot.context.properties.ConfigurationProperties; | |||||
/** | |||||
* <p> | |||||
* 七牛云配置 | |||||
* </p> | |||||
* | |||||
* @author yangkai.shen | |||||
* @date 2022-09-21 16:09 | |||||
*/ | |||||
@Data | |||||
@ConfigurationProperties(prefix = "qiniu") | |||||
public class QiniuProperties { | |||||
private String accessKey; | |||||
private String secretKey; | |||||
private String bucket; | |||||
private String prefix; | |||||
} |
@@ -1,11 +1,13 @@ | |||||
package com.xkcoding.upload.config; | |||||
package com.xkcoding.upload.autoconfigure; | |||||
import com.qiniu.common.Zone; | |||||
import com.qiniu.storage.BucketManager; | import com.qiniu.storage.BucketManager; | ||||
import com.qiniu.storage.Region; | |||||
import com.qiniu.storage.UploadManager; | import com.qiniu.storage.UploadManager; | ||||
import com.qiniu.util.Auth; | import com.qiniu.util.Auth; | ||||
import jakarta.servlet.MultipartConfigElement; | |||||
import jakarta.servlet.Servlet; | |||||
import lombok.RequiredArgsConstructor; | |||||
import org.springframework.beans.factory.annotation.Autowired; | import org.springframework.beans.factory.annotation.Autowired; | ||||
import org.springframework.beans.factory.annotation.Value; | |||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; | import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; | ||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; | import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; | ||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; | import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; | ||||
@@ -17,9 +19,6 @@ import org.springframework.web.multipart.MultipartResolver; | |||||
import org.springframework.web.multipart.support.StandardServletMultipartResolver; | import org.springframework.web.multipart.support.StandardServletMultipartResolver; | ||||
import org.springframework.web.servlet.DispatcherServlet; | import org.springframework.web.servlet.DispatcherServlet; | ||||
import javax.servlet.MultipartConfigElement; | |||||
import javax.servlet.Servlet; | |||||
/** | /** | ||||
* <p> | * <p> | ||||
* 上传配置 | * 上传配置 | ||||
@@ -31,20 +30,11 @@ import javax.servlet.Servlet; | |||||
@Configuration | @Configuration | ||||
@ConditionalOnClass({Servlet.class, StandardServletMultipartResolver.class, MultipartConfigElement.class}) | @ConditionalOnClass({Servlet.class, StandardServletMultipartResolver.class, MultipartConfigElement.class}) | ||||
@ConditionalOnProperty(prefix = "spring.http.multipart", name = "enabled", matchIfMissing = true) | @ConditionalOnProperty(prefix = "spring.http.multipart", name = "enabled", matchIfMissing = true) | ||||
@EnableConfigurationProperties(MultipartProperties.class) | |||||
public class UploadConfig { | |||||
@Value("${qiniu.accessKey}") | |||||
private String accessKey; | |||||
@Value("${qiniu.secretKey}") | |||||
private String secretKey; | |||||
@EnableConfigurationProperties({MultipartProperties.class, QiniuProperties.class}) | |||||
@RequiredArgsConstructor(onConstructor_ = @Autowired) | |||||
public class UploadAutoConfiguration { | |||||
private final MultipartProperties multipartProperties; | private final MultipartProperties multipartProperties; | ||||
@Autowired | |||||
public UploadConfig(MultipartProperties multipartProperties) { | |||||
this.multipartProperties = multipartProperties; | |||||
} | |||||
private final QiniuProperties qiniuProperties; | |||||
/** | /** | ||||
* 上传配置 | * 上传配置 | ||||
@@ -71,7 +61,7 @@ public class UploadConfig { | |||||
*/ | */ | ||||
@Bean | @Bean | ||||
public com.qiniu.storage.Configuration qiniuConfig() { | public com.qiniu.storage.Configuration qiniuConfig() { | ||||
return new com.qiniu.storage.Configuration(Zone.zone0()); | |||||
return new com.qiniu.storage.Configuration(Region.region0()); | |||||
} | } | ||||
/** | /** | ||||
@@ -87,7 +77,7 @@ public class UploadConfig { | |||||
*/ | */ | ||||
@Bean | @Bean | ||||
public Auth auth() { | public Auth auth() { | ||||
return Auth.create(accessKey, secretKey); | |||||
return Auth.create(qiniuProperties.getAccessKey(), qiniuProperties.getSecretKey()); | |||||
} | } | ||||
/** | /** |
@@ -7,10 +7,12 @@ import cn.hutool.core.util.StrUtil; | |||||
import cn.hutool.json.JSONObject; | import cn.hutool.json.JSONObject; | ||||
import cn.hutool.json.JSONUtil; | import cn.hutool.json.JSONUtil; | ||||
import com.qiniu.http.Response; | import com.qiniu.http.Response; | ||||
import com.xkcoding.upload.service.IQiNiuService; | |||||
import com.xkcoding.upload.autoconfigure.QiniuProperties; | |||||
import com.xkcoding.upload.service.QiNiuService; | |||||
import lombok.RequiredArgsConstructor; | |||||
import lombok.extern.slf4j.Slf4j; | import lombok.extern.slf4j.Slf4j; | ||||
import org.springframework.beans.factory.annotation.Autowired; | import org.springframework.beans.factory.annotation.Autowired; | ||||
import org.springframework.beans.factory.annotation.Value; | |||||
import org.springframework.boot.autoconfigure.web.servlet.MultipartProperties; | |||||
import org.springframework.http.MediaType; | import org.springframework.http.MediaType; | ||||
import org.springframework.web.bind.annotation.PostMapping; | import org.springframework.web.bind.annotation.PostMapping; | ||||
import org.springframework.web.bind.annotation.RequestMapping; | import org.springframework.web.bind.annotation.RequestMapping; | ||||
@@ -29,21 +31,22 @@ import java.io.IOException; | |||||
* @author yangkai.shen | * @author yangkai.shen | ||||
* @date Created in 2018-11-06 16:33 | * @date Created in 2018-11-06 16:33 | ||||
*/ | */ | ||||
@RestController | |||||
@Slf4j | @Slf4j | ||||
@RestController | |||||
@RequestMapping("/upload") | @RequestMapping("/upload") | ||||
@RequiredArgsConstructor(onConstructor_ = @Autowired) | |||||
public class UploadController { | public class UploadController { | ||||
@Value("${spring.servlet.multipart.location}") | |||||
private String fileTempPath; | |||||
private final MultipartProperties multipartProperties; | |||||
@Value("${qiniu.prefix}") | |||||
private String prefix; | |||||
private final QiniuProperties qiniuProperties; | |||||
private final IQiNiuService qiNiuService; | |||||
private final QiNiuService qiNiuService; | |||||
@Autowired | |||||
public UploadController(IQiNiuService qiNiuService) { | |||||
this.qiNiuService = qiNiuService; | |||||
private String processLocalTmpFilePath(MultipartFile file) { | |||||
String fileName = file.getOriginalFilename(); | |||||
String rawFileName = StrUtil.subBefore(fileName, ".", true); | |||||
String fileType = StrUtil.subAfter(fileName, ".", true); | |||||
return StrUtil.appendIfMissing(multipartProperties.getLocation(), "/") + rawFileName + "-" + DateUtil.current() + "." + fileType; | |||||
} | } | ||||
@PostMapping(value = "/local", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) | @PostMapping(value = "/local", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) | ||||
@@ -51,10 +54,7 @@ public class UploadController { | |||||
if (file.isEmpty()) { | if (file.isEmpty()) { | ||||
return Dict.create().set("code", 400).set("message", "文件内容为空"); | return Dict.create().set("code", 400).set("message", "文件内容为空"); | ||||
} | } | ||||
String fileName = file.getOriginalFilename(); | |||||
String rawFileName = StrUtil.subBefore(fileName, ".", true); | |||||
String fileType = StrUtil.subAfter(fileName, ".", true); | |||||
String localFilePath = StrUtil.appendIfMissing(fileTempPath, "/") + rawFileName + "-" + DateUtil.current(false) + "." + fileType; | |||||
String localFilePath = processLocalTmpFilePath(file); | |||||
try { | try { | ||||
file.transferTo(new File(localFilePath)); | file.transferTo(new File(localFilePath)); | ||||
} catch (IOException e) { | } catch (IOException e) { | ||||
@@ -63,18 +63,16 @@ public class UploadController { | |||||
} | } | ||||
log.info("【文件上传至本地】绝对路径:{}", localFilePath); | log.info("【文件上传至本地】绝对路径:{}", localFilePath); | ||||
return Dict.create().set("code", 200).set("message", "上传成功").set("data", Dict.create().set("fileName", fileName).set("filePath", localFilePath)); | |||||
return Dict.create().set("code", 200).set("message", "上传成功") | |||||
.set("data", Dict.create().set("fileName", file.getOriginalFilename()).set("filePath", localFilePath)); | |||||
} | } | ||||
@PostMapping(value = "/yun", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) | @PostMapping(value = "/yun", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) | ||||
public Dict yun(@RequestParam("file") MultipartFile file) { | |||||
public Dict qiniu(@RequestParam("file") MultipartFile file) { | |||||
if (file.isEmpty()) { | if (file.isEmpty()) { | ||||
return Dict.create().set("code", 400).set("message", "文件内容为空"); | return Dict.create().set("code", 400).set("message", "文件内容为空"); | ||||
} | } | ||||
String fileName = file.getOriginalFilename(); | |||||
String rawFileName = StrUtil.subBefore(fileName, ".", true); | |||||
String fileType = StrUtil.subAfter(fileName, ".", true); | |||||
String localFilePath = StrUtil.appendIfMissing(fileTempPath, "/") + rawFileName + "-" + DateUtil.current(false) + "." + fileType; | |||||
String localFilePath = processLocalTmpFilePath(file); | |||||
try { | try { | ||||
file.transferTo(new File(localFilePath)); | file.transferTo(new File(localFilePath)); | ||||
Response response = qiNiuService.uploadFile(new File(localFilePath)); | Response response = qiNiuService.uploadFile(new File(localFilePath)); | ||||
@@ -82,19 +80,21 @@ public class UploadController { | |||||
JSONObject jsonObject = JSONUtil.parseObj(response.bodyString()); | JSONObject jsonObject = JSONUtil.parseObj(response.bodyString()); | ||||
String yunFileName = jsonObject.getStr("key"); | String yunFileName = jsonObject.getStr("key"); | ||||
String yunFilePath = StrUtil.appendIfMissing(prefix, "/") + yunFileName; | |||||
String yunFilePath = StrUtil.appendIfMissing(qiniuProperties.getPrefix(), "/") + yunFileName; | |||||
// 删除本地临时文件 | |||||
FileUtil.del(new File(localFilePath)); | FileUtil.del(new File(localFilePath)); | ||||
log.info("【文件上传至七牛云】绝对路径:{}", yunFilePath); | log.info("【文件上传至七牛云】绝对路径:{}", yunFilePath); | ||||
return Dict.create().set("code", 200).set("message", "上传成功").set("data", Dict.create().set("fileName", yunFileName).set("filePath", yunFilePath)); | |||||
return Dict.create().set("code", 200).set("message", "上传成功") | |||||
.set("data", Dict.create().set("fileName", yunFileName).set("filePath", yunFilePath)); | |||||
} else { | } else { | ||||
log.error("【文件上传至七牛云】失败,{}", JSONUtil.toJsonStr(response)); | log.error("【文件上传至七牛云】失败,{}", JSONUtil.toJsonStr(response)); | ||||
FileUtil.del(new File(localFilePath)); | FileUtil.del(new File(localFilePath)); | ||||
return Dict.create().set("code", 500).set("message", "文件上传失败"); | return Dict.create().set("code", 500).set("message", "文件上传失败"); | ||||
} | } | ||||
} catch (IOException e) { | } catch (IOException e) { | ||||
log.error("【文件上传至七牛云】失败,绝对路径:{}", localFilePath); | |||||
log.error("【文件上传至七牛云】失败,绝对路径:{}", localFilePath, e); | |||||
return Dict.create().set("code", 500).set("message", "文件上传失败"); | return Dict.create().set("code", 500).set("message", "文件上传失败"); | ||||
} | } | ||||
} | } | ||||
@@ -1,25 +0,0 @@ | |||||
package com.xkcoding.upload.service; | |||||
import com.qiniu.common.QiniuException; | |||||
import com.qiniu.http.Response; | |||||
import java.io.File; | |||||
/** | |||||
* <p> | |||||
* 七牛云上传Service | |||||
* </p> | |||||
* | |||||
* @author yangkai.shen | |||||
* @date Created in 2018-11-06 17:21 | |||||
*/ | |||||
public interface IQiNiuService { | |||||
/** | |||||
* 七牛云上传文件 | |||||
* | |||||
* @param file 文件 | |||||
* @return 七牛上传Response | |||||
* @throws QiniuException 七牛异常 | |||||
*/ | |||||
Response uploadFile(File file) throws QiniuException; | |||||
} |
@@ -1,15 +1,15 @@ | |||||
package com.xkcoding.upload.service.impl; | |||||
package com.xkcoding.upload.service; | |||||
import com.qiniu.common.QiniuException; | import com.qiniu.common.QiniuException; | ||||
import com.qiniu.http.Response; | import com.qiniu.http.Response; | ||||
import com.qiniu.storage.UploadManager; | import com.qiniu.storage.UploadManager; | ||||
import com.qiniu.util.Auth; | import com.qiniu.util.Auth; | ||||
import com.qiniu.util.StringMap; | import com.qiniu.util.StringMap; | ||||
import com.xkcoding.upload.service.IQiNiuService; | |||||
import com.xkcoding.upload.autoconfigure.QiniuProperties; | |||||
import lombok.RequiredArgsConstructor; | |||||
import lombok.extern.slf4j.Slf4j; | import lombok.extern.slf4j.Slf4j; | ||||
import org.springframework.beans.factory.InitializingBean; | import org.springframework.beans.factory.InitializingBean; | ||||
import org.springframework.beans.factory.annotation.Autowired; | import org.springframework.beans.factory.annotation.Autowired; | ||||
import org.springframework.beans.factory.annotation.Value; | |||||
import org.springframework.stereotype.Service; | import org.springframework.stereotype.Service; | ||||
import java.io.File; | import java.io.File; | ||||
@@ -22,23 +22,16 @@ import java.io.File; | |||||
* @author yangkai.shen | * @author yangkai.shen | ||||
* @date Created in 2018-11-06 17:22 | * @date Created in 2018-11-06 17:22 | ||||
*/ | */ | ||||
@Service | |||||
@Slf4j | @Slf4j | ||||
public class QiNiuServiceImpl implements IQiNiuService, InitializingBean { | |||||
private final UploadManager uploadManager; | |||||
@Service | |||||
@RequiredArgsConstructor(onConstructor_ = @Autowired) | |||||
public class QiNiuService implements InitializingBean { | |||||
private final Auth auth; | private final Auth auth; | ||||
@Value("${qiniu.bucket}") | |||||
private String bucket; | |||||
private final UploadManager uploadManager; | |||||
private final QiniuProperties qiniuProperties; | |||||
private StringMap putPolicy; | private StringMap putPolicy; | ||||
@Autowired | |||||
public QiNiuServiceImpl(UploadManager uploadManager, Auth auth) { | |||||
this.uploadManager = uploadManager; | |||||
this.auth = auth; | |||||
} | |||||
/** | /** | ||||
* 七牛云上传文件 | * 七牛云上传文件 | ||||
@@ -47,7 +40,6 @@ public class QiNiuServiceImpl implements IQiNiuService, InitializingBean { | |||||
* @return 七牛上传Response | * @return 七牛上传Response | ||||
* @throws QiniuException 七牛异常 | * @throws QiniuException 七牛异常 | ||||
*/ | */ | ||||
@Override | |||||
public Response uploadFile(File file) throws QiniuException { | public Response uploadFile(File file) throws QiniuException { | ||||
Response response = this.uploadManager.put(file, file.getName(), getUploadToken()); | Response response = this.uploadManager.put(file, file.getName(), getUploadToken()); | ||||
int retry = 0; | int retry = 0; | ||||
@@ -61,7 +53,8 @@ public class QiNiuServiceImpl implements IQiNiuService, InitializingBean { | |||||
@Override | @Override | ||||
public void afterPropertiesSet() { | public void afterPropertiesSet() { | ||||
this.putPolicy = new StringMap(); | this.putPolicy = new StringMap(); | ||||
putPolicy.put("returnBody", "{\"key\":\"$(key)\",\"hash\":\"$(etag)\",\"bucket\":\"$(bucket)\",\"width\":$(imageInfo.width), \"height\":${imageInfo.height}}"); | |||||
putPolicy.put("returnBody", | |||||
"{\"key\":\"$(key)\",\"hash\":\"$(etag)\",\"bucket\":\"$(bucket)\",\"width\":$(imageInfo.width), \"height\":${imageInfo.height}}"); | |||||
} | } | ||||
/** | /** | ||||
@@ -70,6 +63,6 @@ public class QiNiuServiceImpl implements IQiNiuService, InitializingBean { | |||||
* @return 上传凭证 | * @return 上传凭证 | ||||
*/ | */ | ||||
private String getUploadToken() { | private String getUploadToken() { | ||||
return this.auth.uploadToken(bucket, null, 3600, putPolicy); | |||||
return this.auth.uploadToken(qiniuProperties.getBucket(), null, 3600, putPolicy); | |||||
} | } | ||||
} | } |
@@ -4,17 +4,17 @@ server: | |||||
context-path: /demo | context-path: /demo | ||||
qiniu: | qiniu: | ||||
## 此处填写你自己的七牛云 access key | ## 此处填写你自己的七牛云 access key | ||||
accessKey: | |||||
accessKey: xx | |||||
## 此处填写你自己的七牛云 secret key | ## 此处填写你自己的七牛云 secret key | ||||
secretKey: | |||||
secretKey: xxx | |||||
## 此处填写你自己的七牛云 bucket | ## 此处填写你自己的七牛云 bucket | ||||
bucket: | |||||
bucket: blog | |||||
## 此处填写你自己的七牛云 域名 | ## 此处填写你自己的七牛云 域名 | ||||
prefix: | |||||
prefix: https://static.xkcoding.com/ | |||||
spring: | spring: | ||||
servlet: | servlet: | ||||
multipart: | multipart: | ||||
enabled: true | enabled: true | ||||
location: /Users/yangkai.shen/Documents/code/back-end/spring-boot-demo/spring-boot-demo-upload/tmp | |||||
location: /Users/yangkai.shen/Codes/xkcoding/spring-boot-demo/tmp | |||||
file-size-threshold: 5MB | file-size-threshold: 5MB | ||||
max-file-size: 20MB | |||||
max-file-size: 20MB |
@@ -1,16 +0,0 @@ | |||||
package com.xkcoding.upload; | |||||
import org.junit.Test; | |||||
import org.junit.runner.RunWith; | |||||
import org.springframework.boot.test.context.SpringBootTest; | |||||
import org.springframework.test.context.junit4.SpringRunner; | |||||
@RunWith(SpringRunner.class) | |||||
@SpringBootTest | |||||
public class SpringBootDemoUploadApplicationTests { | |||||
@Test | |||||
public void contextLoads() { | |||||
} | |||||
} |
@@ -0,0 +1,13 @@ | |||||
package com.xkcoding.upload; | |||||
import org.junit.jupiter.api.Test; | |||||
import org.springframework.boot.test.context.SpringBootTest; | |||||
@SpringBootTest | |||||
class UploadApplicationTests { | |||||
@Test | |||||
void contextLoads() { | |||||
} | |||||
} |
@@ -24,6 +24,7 @@ | |||||
<module>demo-base-async</module> | <module>demo-base-async</module> | ||||
<module>demo-base-exception</module> | <module>demo-base-exception</module> | ||||
<module>demo-base-email</module> | <module>demo-base-email</module> | ||||
<module>demo-base-upload</module> | |||||
</modules> | </modules> | ||||
</project> | </project> |