uploadMultipleFiles(@RequestParam("files") MultipartFile[] files) {
+ logger.info("多文件上传本次共接收到{}个文件.", files.length);
+ return Arrays.stream(files).map(this::uploadFile).collect(Collectors.toList());
+ }
+
+}
diff --git a/Springboot-File-Upload-Download/src/main/java/com/button/file/application/exception/FileException.java b/Springboot-File-Upload-Download/src/main/java/com/button/file/application/exception/FileException.java
new file mode 100644
index 0000000000000000000000000000000000000000..02c53cedaeec96bafa83558f12d55dd65cf6e026
--- /dev/null
+++ b/Springboot-File-Upload-Download/src/main/java/com/button/file/application/exception/FileException.java
@@ -0,0 +1,13 @@
+package com.button.file.application.exception;
+
+public class FileException extends RuntimeException {
+ private static final long serialVersionUID = 1L;
+
+ public FileException(String message) {
+ super(message);
+ }
+
+ public FileException(String message, Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/Springboot-File-Upload-Download/src/main/java/com/button/file/application/service/FileDownloadService.java b/Springboot-File-Upload-Download/src/main/java/com/button/file/application/service/FileDownloadService.java
new file mode 100644
index 0000000000000000000000000000000000000000..a5b914507fcd62e030c66ead0c7b0857ce159bf5
--- /dev/null
+++ b/Springboot-File-Upload-Download/src/main/java/com/button/file/application/service/FileDownloadService.java
@@ -0,0 +1,7 @@
+package com.button.file.application.service;
+
+import org.springframework.core.io.Resource;
+
+public interface FileDownloadService {
+ public Resource loadFileAsResource(String fileName);
+}
diff --git a/Springboot-File-Upload-Download/src/main/java/com/button/file/application/service/FileUploadService.java b/Springboot-File-Upload-Download/src/main/java/com/button/file/application/service/FileUploadService.java
new file mode 100644
index 0000000000000000000000000000000000000000..542d57895a45573d8f8755255fe8f3afe5c945f0
--- /dev/null
+++ b/Springboot-File-Upload-Download/src/main/java/com/button/file/application/service/FileUploadService.java
@@ -0,0 +1,7 @@
+package com.button.file.application.service;
+
+import org.springframework.web.multipart.MultipartFile;
+
+public interface FileUploadService {
+ public String storeFile(MultipartFile file);
+}
diff --git a/Springboot-File-Upload-Download/src/main/java/com/button/file/application/service/impl/FileDownloadServiceImpl.java b/Springboot-File-Upload-Download/src/main/java/com/button/file/application/service/impl/FileDownloadServiceImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..3fe76f75e63d35aff4211a516eae4e462f362e15
--- /dev/null
+++ b/Springboot-File-Upload-Download/src/main/java/com/button/file/application/service/impl/FileDownloadServiceImpl.java
@@ -0,0 +1,51 @@
+package com.button.file.application.service.impl;
+
+import java.net.MalformedURLException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.core.io.Resource;
+import org.springframework.core.io.UrlResource;
+import org.springframework.stereotype.Service;
+
+import com.button.file.application.conf.FileLoadProperties;
+import com.button.file.application.exception.FileException;
+import com.button.file.application.service.FileDownloadService;
+
+@Service
+public class FileDownloadServiceImpl implements FileDownloadService {
+ private final Path fileStorageLocation; // 文件在本地存储的地址
+
+ @Autowired
+ public FileDownloadServiceImpl(FileLoadProperties fileProperties) {
+ this.fileStorageLocation = Paths.get(fileProperties.getUploadDir()).toAbsolutePath().normalize();
+ try {
+ Files.createDirectories(this.fileStorageLocation);
+ } catch (Exception ex) {
+ throw new FileException("保存文件创建目录时发生异常. .", ex);
+ }
+ }
+
+ /**
+ * 加载文件
+ *
+ * @param fileName 文件名
+ * @return 文件
+ */
+ @Override
+ public Resource loadFileAsResource(String fileName) {
+ try {
+ Path filePath = this.fileStorageLocation.resolve(fileName).normalize();
+ Resource resource = new UrlResource(filePath.toUri());
+ if (resource.exists()) {
+ return resource;
+ } else {
+ throw new FileException("File not found " + fileName);
+ }
+ } catch (MalformedURLException ex) {
+ throw new FileException("File not found " + fileName, ex);
+ }
+ }
+}
diff --git a/Springboot-File-Upload-Download/src/main/java/com/button/file/application/service/impl/FileUploadServiceImpl.java b/Springboot-File-Upload-Download/src/main/java/com/button/file/application/service/impl/FileUploadServiceImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..9f417e9ab69da5ab902376b0a0a263f909804203
--- /dev/null
+++ b/Springboot-File-Upload-Download/src/main/java/com/button/file/application/service/impl/FileUploadServiceImpl.java
@@ -0,0 +1,51 @@
+package com.button.file.application.service.impl;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.StandardCopyOption;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.util.StringUtils;
+import org.springframework.web.multipart.MultipartFile;
+
+import com.button.file.application.conf.FileLoadProperties;
+import com.button.file.application.exception.FileException;
+import com.button.file.application.service.FileUploadService;
+
+@Service
+public class FileUploadServiceImpl implements FileUploadService {
+ private final Path fileStorageLocation; // 文件在本地存储的地址
+ @Autowired
+ public FileUploadServiceImpl(FileLoadProperties fileProperties) {
+ this.fileStorageLocation = Paths.get(fileProperties.getUploadDir()).toAbsolutePath().normalize();
+ try {
+ Files.createDirectories(this.fileStorageLocation);
+ } catch (Exception ex) {
+ throw new FileException("保存文件创建文件夹时出现异常.", ex);
+ }
+ }
+
+ /**
+ * 存储文件到系统
+ *
+ * @param file 文件
+ * @return 文件名
+ */
+ @Override
+ public String storeFile(MultipartFile file) {
+ String fileName = StringUtils.cleanPath(file.getOriginalFilename());
+ try {
+ if (fileName.contains("..")) {
+ throw new FileException("抱歉,文件名包含不合法的字符." + fileName);
+ }
+ Path targetLocation = this.fileStorageLocation.resolve(fileName);
+ Files.copy(file.getInputStream(), targetLocation, StandardCopyOption.REPLACE_EXISTING);
+ return fileName;
+ } catch (IOException ex) {
+ throw new FileException("保存文件:" + fileName + "时出现异常,请重试!!", ex);
+ }
+ }
+}
diff --git a/Springboot-File-Upload-Download/src/main/java/com/button/file/application/utils/UploadFileResponse.java b/Springboot-File-Upload-Download/src/main/java/com/button/file/application/utils/UploadFileResponse.java
new file mode 100644
index 0000000000000000000000000000000000000000..fdcf9bdff76e927e516b42663bd52d79178a8731
--- /dev/null
+++ b/Springboot-File-Upload-Download/src/main/java/com/button/file/application/utils/UploadFileResponse.java
@@ -0,0 +1,53 @@
+package com.button.file.application.utils;
+
+public class UploadFileResponse {
+ private String fileName;
+ private String fileDownloadUri;
+ private String fileType;
+ private long size;
+
+ public UploadFileResponse(String fileName, String fileDownloadUri, String fileType, long size) {
+ this.fileName = fileName;
+ this.fileDownloadUri = fileDownloadUri;
+ this.fileType = fileType;
+ this.size = size;
+ }
+
+ public String getFileName() {
+ return fileName;
+ }
+
+ public void setFileName(String fileName) {
+ this.fileName = fileName;
+ }
+
+ public String getFileDownloadUri() {
+ return fileDownloadUri;
+ }
+
+ public void setFileDownloadUri(String fileDownloadUri) {
+ this.fileDownloadUri = fileDownloadUri;
+ }
+
+ public String getFileType() {
+ return fileType;
+ }
+
+ public void setFileType(String fileType) {
+ this.fileType = fileType;
+ }
+
+ public long getSize() {
+ return size;
+ }
+
+ public void setSize(long size) {
+ this.size = size;
+ }
+
+ @Override
+ public String toString() {
+ return "UploadFileResponse [fileName=" + fileName + ", fileDownloadUri=" + fileDownloadUri + ", fileType="
+ + fileType + ", size=" + size + "]";
+ }
+}
diff --git a/Springboot-File-Upload-Download/src/main/resources/application.yml b/Springboot-File-Upload-Download/src/main/resources/application.yml
new file mode 100644
index 0000000000000000000000000000000000000000..67dc2ec73adec21d0945d6a3e25bf803a25eae60
--- /dev/null
+++ b/Springboot-File-Upload-Download/src/main/resources/application.yml
@@ -0,0 +1,22 @@
+server:
+ servlet:
+ context-path: /file
+ port: 8080
+ uri-encoding: utf-8
+
+logging:
+ config: classpath:logback.xml
+
+## MULTIPART (MultipartProperties)
+# 开启 multipart 上传功能
+spring:
+ servlet:
+ multipart:
+ enabled: true
+ file-size-threshold: 2KB # 文件写入磁盘的阈值
+ max-file-size: 200MB # 最大文件大小
+ max-request-size: 215MB # 最大请求大小
+
+## 文件存储所需参数
+# 所有通过 REST APIs 上传的文件都将存储在此目录下
+file.upload-dir: ./uploads
diff --git a/Springboot-File-Upload-Download/src/main/resources/logback.xml b/Springboot-File-Upload-Download/src/main/resources/logback.xml
new file mode 100644
index 0000000000000000000000000000000000000000..0d995394912fce7deaf09796d78b9ceb20e82b92
--- /dev/null
+++ b/Springboot-File-Upload-Download/src/main/resources/logback.xml
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+
+ %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} -%msg%n
+
+
+
+
+ ${LOG_HOME}/button_api.log
+
+
+
+ ${LOG_HOME}/button_api.log.%d{yyyy-MM-dd}.%i.log
+
+
+
+ 100MB
+
+
+
+
+ %d{HH:mm:ss.SSS} [%thread] %-5level %logger{50} -%msg%n
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Springboot-File-Upload-Download/src/main/resources/static/css/main.css b/Springboot-File-Upload-Download/src/main/resources/static/css/main.css
new file mode 100644
index 0000000000000000000000000000000000000000..0f627f4fe8c6afd9b29815855797f5fcf4fcfee2
--- /dev/null
+++ b/Springboot-File-Upload-Download/src/main/resources/static/css/main.css
@@ -0,0 +1,131 @@
+* {
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+}
+
+body {
+ margin: 0;
+ padding: 0;
+ font-weight: 400;
+ font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
+ font-size: 1rem;
+ line-height: 1.58;
+ color: #333;
+ background-color: #f4f4f4;
+}
+
+body:before {
+ height: 50%;
+ width: 100%;
+ position: absolute;
+ top: 0;
+ left: 0;
+ background: #128ff2;
+ content: "";
+ z-index: 0;
+}
+
+.clearfix:after {
+ display: block;
+ content: "";
+ clear: both;
+}
+
+
+h1, h2, h3, h4, h5, h6 {
+ margin-top: 20px;
+ margin-bottom: 20px;
+}
+
+h1 {
+ font-size: 1.7em;
+}
+
+a {
+ color: #128ff2;
+}
+
+button {
+ box-shadow: none;
+ border: 1px solid transparent;
+ font-size: 14px;
+ outline: none;
+ line-height: 100%;
+ white-space: nowrap;
+ vertical-align: middle;
+ padding: 0.6rem 1rem;
+ border-radius: 2px;
+ transition: all 0.2s ease-in-out;
+ cursor: pointer;
+ min-height: 38px;
+}
+
+button.primary {
+ background-color: #128ff2;
+ box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.12);
+ color: #fff;
+}
+
+input {
+ font-size: 1rem;
+}
+
+input[type="file"] {
+ border: 1px solid #128ff2;
+ padding: 6px;
+ max-width: 100%;
+}
+
+.file-input {
+ width: 100%;
+}
+
+.submit-btn {
+ display: block;
+ margin-top: 15px;
+ min-width: 100px;
+}
+
+@media screen and (min-width: 500px) {
+ .file-input {
+ width: calc(100% - 115px);
+ }
+
+ .submit-btn {
+ display: inline-block;
+ margin-top: 0;
+ margin-left: 10px;
+ }
+}
+
+.upload-container {
+ max-width: 700px;
+ margin-left: auto;
+ margin-right: auto;
+ background-color: #fff;
+ box-shadow: 0 1px 11px rgba(0, 0, 0, 0.27);
+ margin-top: 60px;
+ min-height: 400px;
+ position: relative;
+ padding: 20px;
+}
+
+.upload-header {
+ border-bottom: 1px solid #ececec;
+}
+
+.upload-header h2 {
+ font-weight: 500;
+}
+
+.single-upload {
+ padding-bottom: 20px;
+ margin-bottom: 20px;
+ border-bottom: 1px solid #e8e8e8;
+}
+
+.upload-response {
+ overflow-x: hidden;
+ word-break: break-all;
+}
\ No newline at end of file
diff --git a/Springboot-File-Upload-Download/src/main/resources/static/index.html b/Springboot-File-Upload-Download/src/main/resources/static/index.html
new file mode 100644
index 0000000000000000000000000000000000000000..9116352cb4901faad19e7e517436d53986d0c1f7
--- /dev/null
+++ b/Springboot-File-Upload-Download/src/main/resources/static/index.html
@@ -0,0 +1,56 @@
+
+
+
+
+
+ Spring Boot File Upload / Download Rest API Example
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Springboot-File-Upload-Download/src/main/resources/static/js/main.js b/Springboot-File-Upload-Download/src/main/resources/static/js/main.js
new file mode 100644
index 0000000000000000000000000000000000000000..5418f386ca6066f45e890faad1d033aeabae4d00
--- /dev/null
+++ b/Springboot-File-Upload-Download/src/main/resources/static/js/main.js
@@ -0,0 +1,115 @@
+'use strict';
+
+var singleUploadForm = document.querySelector('#singleUploadForm');
+var singleFileUploadInput = document.querySelector('#singleFileUploadInput');
+var singleFileUploadError = document.querySelector('#singleFileUploadError');
+var singleFileUploadSuccess = document.querySelector('#singleFileUploadSuccess');
+
+var multipleUploadForm = document.querySelector('#multipleUploadForm');
+var multipleFileUploadInput = document.querySelector('#multipleFileUploadInput');
+var multipleFileUploadError = document.querySelector('#multipleFileUploadError');
+var multipleFileUploadSuccess = document.querySelector('#multipleFileUploadSuccess');
+
+var fileDownloadForm = document.querySelector('#fileDownloadForm');
+var fileDownloadInput = document.querySelector('#fileDownloadInput');
+var downloadError = document.querySelector('#downloadError');
+var downloadSuccess = document.querySelector('#downloadSuccess');
+
+function uploadSingleFile(file) {
+ var formData = new FormData();
+ formData.append("file", file);
+
+ var xhr = new XMLHttpRequest();
+ xhr.open("POST", "/file/uploadFile");
+
+ xhr.onload = function() {
+ console.log(xhr.responseText);
+ var response = JSON.parse(xhr.responseText);
+ if(xhr.status == 200) {
+ singleFileUploadError.style.display = "none";
+ singleFileUploadSuccess.innerHTML = "文件上传成功.
DownloadUrl : " + response.fileDownloadUri + "
";
+ singleFileUploadSuccess.style.display = "block";
+ } else {
+ singleFileUploadSuccess.style.display = "none";
+ singleFileUploadError.innerHTML = (response && response.message) || "Some Error Occurred";
+ }
+ }
+
+ xhr.send(formData);
+}
+
+function uploadMultipleFiles(files) {
+ var formData = new FormData();
+ for(var index = 0; index < files.length; index++) {
+ formData.append("files", files[index]);
+ }
+
+ var xhr = new XMLHttpRequest();
+ xhr.open("POST", "/file/uploadMultipleFiles");
+
+ xhr.onload = function() {
+ console.log(xhr.responseText);
+ var response = JSON.parse(xhr.responseText);
+ if(xhr.status == 200) {
+ multipleFileUploadError.style.display = "none";
+ var content = "所有文件均已上传成功.
";
+ for(var i = 0; i < response.length; i++) {
+ content += "DownloadUrl : " + response[i].fileDownloadUri + "
";
+ }
+ multipleFileUploadSuccess.innerHTML = content;
+ multipleFileUploadSuccess.style.display = "block";
+ } else {
+ multipleFileUploadSuccess.style.display = "none";
+ multipleFileUploadError.innerHTML = (response && response.message) || "Some Error Occurred";
+ }
+ }
+
+ xhr.send(formData);
+}
+
+
+singleUploadForm.addEventListener('submit', function(event){
+ var files = singleFileUploadInput.files;
+ if(files.length === 0) {
+ singleFileUploadError.innerHTML = "请选择一个文件!";
+ singleFileUploadError.style.display = "block";
+ }
+ uploadSingleFile(files[0]);
+ event.preventDefault();
+}, true);
+
+
+multipleUploadForm.addEventListener('submit', function(event){
+ var files = multipleFileUploadInput.files;
+ if(files.length === 0) {
+ multipleFileUploadError.innerHTML = "请至少选择一个文件!";
+ multipleFileUploadError.style.display = "block";
+ }
+ uploadMultipleFiles(files);
+ event.preventDefault();
+}, true);
+
+function downLoadFile(fileName) {
+ var xhr = new XMLHttpRequest();
+ xhr.open("GET", "/file/downloadFile/" + fileName, true);
+ xhr.onload = function() {
+ console.log(xhr);
+ if(xhr.status == 200) {
+ window.open('/file/downloadFile/' + fileName);
+ downloadError.style.display = "none";
+ downloadSuccess.innerHTML = "文件下载成功!";
+ downloadSuccess.style.display = "block";
+ } else {
+ downloadSuccess.style.display = "none";
+ downloadError.innerHTML = "文件不存在或文件下载失败,请检查文件名!!";
+ downloadError.style.display = "block";
+ }
+ }
+ xhr.send(null);
+}
+fileDownloadForm.addEventListener('submit', function(event){
+ var fileName = fileDownloadInput.value;
+ console.log(fileName);
+ downLoadFile(fileName);
+ event.preventDefault();
+}, true);