文件上传和下载
application.properties
## MULTIPART (MultipartProperties)
# 开启 multipart 上传功能
spring.servlet.multipart.enabled=true
# 文件写入磁盘的阈值
spring.servlet.multipart.file-size-threshold=2KB
# 最大文件大小
spring.servlet.multipart.max-file-size=200MB
# 最大请求大小
spring.servlet.multipart.max-request-size=215MB
## 文件存储所需参数
# 所有通过 REST APIs 上传的文件都将存储在此目录下
file.uploadDir=C:\\Users\\Yuri\\Desktop\\TRY
FileService
package yuri.newfile.demo.service;
import org.springframework.core.io.UrlResource;
import org.springframework.util.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import yuri.newfile.demo.pojo.FileProperties;
import yuri.newfile.demo.util.FileException;
import org.springframework.core.io.Resource;
import java.io.IOException;
import java.net.MalformedURLException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
@Service
public class FileService {
private final Path fileStorageLocation;
@Autowired
public FileService(FileProperties fileProperties) {
this.fileStorageLocation = Paths.get(fileProperties.getUploadDir()).toAbsolutePath().normalize();
try {
Files.createDirectories(this.fileStorageLocation);
} catch (Exception e) {
throw new FileException("不能创建上传文件储存路径");
}
}
public String storeFile(MultipartFile file) {
// file.getOriginalFilename()返回文件名,但某些浏览器下会返回带盘符的路径,所以用StringUtils.cleanPath()进行处理
String fileName = StringUtils.cleanPath(file.getOriginalFilename());
try{
// 检查文件名是否含有非法字符
if (fileName.contains("..")){
throw new FileException("文件名含有非法字符");
}
// resolve()把存储路径fileStorageLocation和文件名fileName合并为一条路径
// C:\Users\Yuri\Desktop\TRY+xxx = C:\Users\Yuri\Desktop\TRY\xxx
Path path = this.fileStorageLocation.resolve(fileName);
// 对文件进行存储操作,三个参数分别是输入流、路径、(枚举)操作参数
Files.copy(file.getInputStream(), path, StandardCopyOption.REPLACE_EXISTING);
return fileName;
}catch (IOException e){
throw new FileException("不能存储文件:" + fileName);
}
}
public Resource loadFileAsResource(String fileName) {
try{
Path filePath = this.fileStorageLocation.resolve(fileName).normalize();
Resource resource = new UrlResource(filePath.toUri());
// System.out.println(filePath);
// System.out.println(filePath.toUri());
// System.out.println(resource);
if(resource.exists()){
return resource;
}else{
throw new FileException("未找到文件:" + fileName);
}
} catch (MalformedURLException e) {
throw new FileException("未找到文件:" + fileName, e);
}
}
}
FileController
package yuri.newfile.demo.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.servlet.ModelAndView;
import yuri.newfile.demo.service.FileService;
import yuri.newfile.demo.util.UploadFileResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.support.ServletUriComponentsBuilder;
import javax.naming.Context;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import static org.springframework.web.servlet.function.RequestPredicates.contentType;
@RestController
public class FileController {
private static final Logger logger = LoggerFactory.getLogger(FileController.class);
@Autowired
private FileService fileService;
@PostMapping("/uploadFile")
public UploadFileResponse uploadFileResponse(@RequestParam("file")MultipartFile file){
// 对文件进行存储操作
String fileName = fileService.storeFile(file);
// 对返回参数进行设置
// ServletUriComponentsBuilder构建Url地址,
// fromCurrentContextPath()为本机IP,比如http://localhost:8080
// path是对后续路径进行增添
// toUrlString是进行Url地址转义,因为起初构建的并不是标准url地址
String fileDownloadUri = ServletUriComponentsBuilder.fromCurrentContextPath()
.path("/downloadFile/")
.path(fileName)
.toUriString();
// 返回此次传输的UploadFileResponse对象
return new UploadFileResponse(fileName, fileDownloadUri,
file.getContentType(), file.getSize());
}
@PostMapping("/uploadFiles")
public List<UploadFileResponse> uploadFileResponses(@RequestParam("files") MultipartFile[] files){
// Java8新特性:Stream()将数组转换为流,map()是过滤操作,此处过滤方法为uploadFileResponse,collect(Collectors.toList())是固定写法,将结果转为List
return Arrays.stream(files)
.map(this::uploadFileResponse)
.collect(Collectors.toList());
}
@GetMapping("/downloadFile/{fileName:.+}")
// @PathVariable可以把url{}中变量赋值给参数,当不写value就对应名字自动赋值
public ResponseEntity<Resource> downloadFile(@PathVariable String fileName, HttpServletRequest request){
Resource resource = fileService.loadFileAsResource(fileName);
String contentType = null;
try{
// getMimeType()获取文件的格式,是ServletContext的一个方法
contentType = request.getServletContext().getMimeType(resource.getFile().getAbsolutePath());
} catch (IOException e){
logger.info("不能确定文件类型");
}
if (contentType == null) {
contentType = "application/octet-stream";
}
// 进行文件下载处理
return ResponseEntity.ok()
.contentType(MediaType.parseMediaType(contentType))
.header(HttpHeaders.CONTENT_DISPOSITION,
"attachment; filename=\"" +resource.getFilename() + "\"")
.body(resource);
}
}
代码参考
https://www.jianshu.com/p/e25b3c542553
项目代码
链接:https://pan.baidu.com/s/1iWLCq2cdko_Bu4O9-ceVEg
提取码:Yuri
以上