SpringBoot:文件上传和下载

发布于 2020-12-17  1639 次阅读


2021年12月1日更新:

上传模块之前是直接调用transferTo方法存储

今天看到一个新的存储方法,把MultipartFile文件类型转换成byte[] 数组,然后传输byte数组实现文件的上传。比如使用了fastDFS的系统,调用FastFileStorageClient客户端方法,进行存储

 String filename = file.getOriginalFilename();
 byte[] byteArray = IOUtils.toByteArray(file.getInputStream());

还有一种就是通过base64来上传文件,核心都是一样的,主要区别就是把base64转换成byte[]数组

String fileBase64 = upLoadReqDto.getFileBase64();
byte[] bytes = Base64.getDecoder().decode(fileBase64.getBytes(StandardCharsets.UTF_8));

加上文件类型判断。

FILETYPE = "xml,html,jsp,exe,jar"
    public UploadFileResDto uploadFile(MultipartFile file) {
        try {
            String filename = file.getOriginalFilename();
            byte[] byteArray = IOUtils.toByteArray(file.getInputStream());
            //在文件上传时,有时候我们需要判断文件类型。但是又不能简单的通过扩展名来判断(防止恶意脚本等通过上传到服务器上),
            //于是我们需要在服务端通过读取文件的首部几个二进制位来判断常用的文件类型。使用hutool文件类型工具类判断.
            //这些类型已经涵盖了常用的图片、音频、视频、Office文档类型,其余文件类型为null。即可以应对大部分的使用场景。
            String type = FileTypeUtil.getType(file.getInputStream());
            String fileSuffix = FileUtil.getSuffix(filename);

            log.info("文件类型是:{},文件后缀名是:{}" + type, fileSuffix);
            if (StringUtils.isBlank(fileSuffix)) {
                log.error("文件后缀名非法");
                throw new RuntimeException("文件上传失败,文件后缀名非法~");
            }

            if (StringUtils.isBlank(type) || FILETYPE.contains(fileSuffix) || FILETYPE.contains(fileSuffix.toLowerCase())) {
                log.error("不支持此文件格式{}", StringUtils.isNotBlank(type) ? type : fileSuffix);
                throw new RuntimeException("文件上传失败,不支持此文件格式~");
            }

            return applicationService.upload(byteArray, filename);
        } catch (IOException e) {

            log.error("上传文件失败", e);
            throw new RuntimeException("文件上传失败!");
        }

    }

配置文件

# 上传文件总的最大值
spring.servlet.multipart.max-request-size=10MB
# 单个文件的最大值
spring.servlet.multipart.max-file-size=10MB

单文件

@PostMapping("/upload")
    @ResponseBody
    public String upload(@RequestParam("file") MultipartFile file) {
        if (file.isEmpty()) {
            return "上传失败,请选择文件";
        }

        String fileName = file.getOriginalFilename();
        String filePath = "/Users/itinypocket/workspace/temp/";
        File dest = new File(filePath + fileName);
        try {
            file.transferTo(dest);
            LOGGER.info("上传成功");
            return "上传成功";
        } catch (IOException e) {
            LOGGER.error(e.toString(), e);
        }
        return "上传失败!";
    }

多文件

@PostMapping("/standardServletMultipartResolver")
public String standardServletMultipartResolver(@RequestParam(name = "file") MultipartFile[] multipartFiles) {
    Assert.isTrue(multipartFiles != null && multipartFiles.length > 0, "请选择文件");
    //业务逻辑
    return "上传成功!";
}

文件下载

@RequestMapping("/download")
    public String fileDownLoad(HttpServletResponse response, @RequestParam("fileName") String fileName){
        File file = new File(downloadFilePath +'/'+ fileName);
        if(!file.exists()){
            return "下载文件不存在";
        }
        response.reset();
        response.setContentType("application/octet-stream");
        response.setCharacterEncoding("utf-8");
        response.setContentLength((int) file.length());
        response.setHeader("Content-Disposition", "attachment;filename=" + fileName );

        try(BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));) {
            byte[] buff = new byte[1024];
            OutputStream os  = response.getOutputStream();
            int i = 0;
            while ((i = bis.read(buff)) != -1) {
                os.write(buff, 0, i);
                os.flush();
            }
        } catch (IOException e) {
            log.error("{}",e);
            return "下载失败";
        }
        return "下载成功";
    }

@RequestParm 与 @RequestPart 作用场景

@RequestParam:请求参数到处理器功能处理方法的方法参数上的绑定;


@RequestPart:提供对“multipart/form-data”请求的全面支持,支持Servlet 3.0文件上传(javax.servlet.http.Part)、支持内容的HttpMessageConverter(即根据请求头的Content-Type,来判断内容区数据是什么类型,如JSON、XML,能自动转换为命令对象),比@RequestParam更强大(只能对请求参数数据绑定,key-alue格式),而@RequestPart支持如JSON、XML内容区数据的绑定;


欢迎欢迎~热烈欢迎~