文件上传和下载

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

以上
posted @ 2020-11-18 15:59  AkimotoAkira  阅读(131)  评论(0编辑  收藏  举报