Spring對文件上傳做了簡單的封裝,就是用MultipartFile這個對象去接收文件,當然有很多種寫法,下面會一一介紹。
文件的下載很簡單,給一個鏈接就行,而這個鏈接怎么生成,也有很多方式,下面也會講解下常用的方式。
application.properties 中需要添加下面的配置:
spring.servlet.multipart.enabled=true spring.servlet.multipart.max-file-size=20MB spring.servlet.multipart.max-request-size=50MB
這里,
- spring.servlet.multipart.max-file-size是對單個文件大小的限制。
- spring.servlet.multipart.max-request-size是對單次請求的大小進行限制
至此,已經可以正常的進行上傳下載了,就剩下寫代碼了。
文件上傳的幾種方式
在Controller的RequestMapping注解的方法參數中,直接將MultipartFile作為參數傳遞進來。
package com.cff.springbootwork.web.file;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import com.cff.springbootwork.dto.ResultModel;
import com.cff.springbootwork.service.UploadService;
@RestController
@RequestMapping("/file")
public class FileRest {
private Logger log = LoggerFactory.getLogger(this.getClass());
@Value("${upload.static.url}")
private String uploadStaticUrl;
@Autowired
UploadService uploadService;
@RequestMapping("/upload")
public ResultModel upload(@RequestParam("files") MultipartFile file) {
try {
if (file.isEmpty()) {
return ResultModel.error("文件不能為空!");
}
String fileName = uploadService.saveUploadFile(file);
return ResultModel.ok(uploadStaticUrl + fileName);
} catch (Exception e) {
e.printStackTrace();
log.error("文件上傳失敗!", e);
return ResultModel.error("文件上傳失敗!");
}
}
}
測試的時候,使用postman可以這樣傳參:

2.2 多個文件上傳
在Controller的RequestMapping注解的方法參數中,直接將MultipartFile作為list傳遞進來。在FileRest中增加uploadList方法。
package com.cff.springbootwork.web.file;
import java.util.ArrayList;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import com.cff.springbootwork.dto.ResultModel;
import com.cff.springbootwork.service.UploadService;
@RestController
@RequestMapping("/file")
public class FileRest {
private Logger log = LoggerFactory.getLogger(this.getClass());
@Value("${upload.static.url}")
private String uploadStaticUrl;
@Autowired
UploadService uploadService;
@RequestMapping("/upload")
public ResultModel upload(@RequestParam("files") MultipartFile file) {
try {
if (file.isEmpty()) {
return ResultModel.error("文件不能為空!");
}
String fileName = uploadService.saveUploadFile(file);
return ResultModel.ok(uploadStaticUrl + fileName);
} catch (Exception e) {
e.printStackTrace();
log.error("文件上傳失敗!", e);
return ResultModel.error("文件上傳失敗!");
}
}
@RequestMapping("/uploadList")
public ResultModel uploadList(@RequestParam("files") List<MultipartFile> fileList) {
try {
List<String> list = new ArrayList<>();
for (MultipartFile file : fileList) {
String fileName = uploadService.saveUploadFile(file);
list.add(uploadStaticUrl + fileName);
}
return ResultModel.ok(list);
} catch (Exception e) {
e.printStackTrace();
log.error("文件上傳失敗!", e);
return ResultModel.error("文件上傳失敗!");
}
}
}
測試的時候,使用postman可以這樣傳參:

從HttpServletRequest中取文件
新建uploadByRequest方法,將HttpServletRequest作為參數,Spring自動傳入。
Spring對Request做了一層封裝,如果有文件,它就是MultipartHttpServletRequest。
然后我們可以從MultipartHttpServletRequest獲取到MultipartFile。后面的處理方式一樣了。
package com.cff.springbootwork.web.file;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import com.cff.springbootwork.dto.ResultModel;
import com.cff.springbootwork.service.UploadService;
@RestController
@RequestMapping("/file")
public class FileRest {
private Logger log = LoggerFactory.getLogger(this.getClass());
@Value("${upload.static.url}")
private String uploadStaticUrl;
@Autowired
UploadService uploadService;
@RequestMapping("/upload")
public ResultModel upload(@RequestParam("files") MultipartFile file) {
try {
if (file.isEmpty()) {
return ResultModel.error("文件不能為空!");
}
String fileName = uploadService.saveUploadFile(file);
return ResultModel.ok(uploadStaticUrl + fileName);
} catch (Exception e) {
e.printStackTrace();
log.error("文件上傳失敗!", e);
return ResultModel.error("文件上傳失敗!");
}
}
@RequestMapping("/uploadList")
public ResultModel uploadList(@RequestParam("files") List<MultipartFile> fileList) {
try {
List<String> list = new ArrayList<>();
for (MultipartFile file : fileList) {
String fileName = uploadService.saveUploadFile(file);
list.add(uploadStaticUrl + fileName);
}
return ResultModel.ok(list);
} catch (Exception e) {
e.printStackTrace();
log.error("文件上傳失敗!", e);
return ResultModel.error("文件上傳失敗!");
}
}
@RequestMapping("/uploadByRequest")
public ResultModel uploadByRequest(HttpServletRequest request) {
try {
Map<String, MultipartFile> files = new HashMap<>();
if (request instanceof MultipartHttpServletRequest) {
MultipartHttpServletRequest req = (MultipartHttpServletRequest) request;
MultiValueMap<String, MultipartFile> multiValueMap = req.getMultiFileMap();
if (multiValueMap != null && !multiValueMap.isEmpty()) {
for (String key : multiValueMap.keySet()) {
files.put(key, multiValueMap.getFirst(key));
}
}
}
if (files.isEmpty())
return ResultModel.error("文件木有?");
List<String> list = new ArrayList<>();
for (MultipartFile file : files.values()) {
String fileName = uploadService.saveUploadFile(file);
list.add(uploadStaticUrl + fileName);
}
return ResultModel.ok(list);
} catch (Exception e) {
e.printStackTrace();
log.error("文件上傳失敗!", e);
return ResultModel.error("文件上傳失敗!");
}
}
}
測試的時候,傳參方式使用上面兩種都可以了。
三、文件下載方式
文件上傳成功后,我們同時會提供下載功能。下載功能很簡單,有以下幾種方式:
3.1 Spring配置映射
新建一個WebStaticConfig配置類,實現WebMvcConfigurer接口即可:
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebStaticConfig implements WebMvcConfigurer {
@Value("${upload.static.local}")
private String uploadStaticLocal;
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/static/**").addResourceLocations("file:" + uploadStaticLocal);
}
public String getUploadStaticLocal() {
return uploadStaticLocal;
}
public void setUploadStaticLocal(String uploadStaticLocal) {
this.uploadStaticLocal = uploadStaticLocal;
}
}
這句話將當前服務器(比如是http://127.0.0.1:8080)的/static路徑(http://127.0.0.1:8080/static/)下的資源,映射到uploadStaticLocal指定的本地路徑下的文件。
然后我們就可以直接訪問文件了。
3.2 代理(nginx)映射
代理首選nginx了。高性能快捷的代理轉發工具。
比如要將http://127.0.0.1:8081/static/下的資源,映射到/static/指定的本地路徑下的文件,可以這樣配置
server {
listen 8081;
server_name localhost;
location /static {
alias /static/;
index index.html;
}
}
這里為什么用8081而不是上面的8080了呢?因為上面的8080端口已經被SpringBoot應用占用了。nginx要在另一個端口監聽了,如果非要將SpringBoot應用和靜態資源在一個端口,可以對SpringBoot應用也做代理,例如:
server { listen 8081; server_name localhost; location ^~ /api/ { proxy_pass http://127.0.0.1:8080/; } location /static { alias /static/; index index.html; } }
3.3 ResponseEntity讀取文件並返回
比如我們在FileRest的Controller中建立個downloadFile方法,傳入文件名,將文件讀取為byte,包裝成ResponseEntity返回。
@RequestMapping(value = "/downloadFile", method = { RequestMethod.GET }) public ResponseEntity<byte[]> downloadFile(@RequestParam("fileName") String fileName) { try { File file = new File(fileName); byte[] body = null; InputStream is = new FileInputStream(file); body = new byte[is.available()]; is.read(body); is.close(); HttpHeaders headers = new HttpHeaders(); headers.add("Content-Disposition", "attchement;filename=" + file.getName()); HttpStatus statusCode = HttpStatus.OK; ResponseEntity<byte[]> entity = new ResponseEntity<byte[]>(body, headers, statusCode); return entity; } catch (Exception e) { e.printStackTrace(); return null; } }
