zoukankan      html  css  js  c++  java
  • SpringBoot的文件上传与下载

    SpringBoot的文件上传与下载

    技术概述

      文件的上传与下载是Web应用常用的功能。例如本博客园就拥有文件上传和附件下载的功能。博客内容也可直接上传图片并显示。SpringBoot是Web应用开发的主流框架,支持文件上传与下载操作。其中文件上传可分为单文件上传和多文件上传。

    SpringBoot的文件上传下载实现大致步骤如下

    1. 前端编写上传控件
    2. 在Controller分别实现单文件上传、多文件上传与文件下载方法
    3. (可选)进行文件上传相关配置

    具体实现步骤

    1)前端上传控件编写

      注意声明form的enctype属性为multipart/form-data

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>文件上传</title>
    </head>
    <body>
        <h3>单文件上传</h3>
        <form method="post" action="upload" enctype="multipart/form-data">
            <input type="file" name="file"/>
            <br/><br/>
            <input type="submit" value="上传">
        </form>
        <br/><hr/>
        <h3>多文件上传</h3>
        <form method="post" action="multiUpload" enctype="multipart/form-data">
            <input type="file" name="file" value="选择文件1"/>
            <br/><br/>
            <input type="file" name="file" value="选择文件2"/>
            <br/><br/>
            <input type="submit" value="上传">
        </form>
    </body>
    </html>
    

    2)声明文件上传与下载路径常量

      一般而言,文件保存路径和下载路径是固定的,因此最好将其声明为常量,当路径要修改时也只需修改常量即可。

    private static final String UPLOAD_PATH = "C:/Temp/";
    private static final String DOWNLOAD_PATH = "C:/Java/";
    

    3)实现文件上传方法

    文件上传方法的思路主要如下

    1. 空文件不执行上传操作。
    2. 给文件按照一定的命名规则进行重命名。此举即可以防止命名冲突,也可以从一定程度上防止病毒木马等入侵,此处采用UUID实现重命名,当然也可以采取其它命名策略(如SHA、MD5等),但是要保证命名的合理性和安全性。
    3. 若文件命名策略可能生成同名文件(如两个用户上传了同一个文件),可采用后上传的文件不执行保存操作。
    @PostMapping("upload")
    @ResponseBody
    public String upload(@RequestParam("file") MultipartFile file) {
        //不可以上传空文件
        if(file.isEmpty()) {
            return "文件为空,请选择文件后再上传";
        }
    
        String filename = file.getOriginalFilename();
        String suffix = filename.substring(filename.lastIndexOf("."));
        filename = UPLOAD_PATH + UUID.randomUUID() + suffix;
        File dest = new File(filename);
    
        //若文件已存在则不执行保存操作
        try {
            if(!dest.exists()) {
                file.transferTo(dest);
            }
        } catch (Exception e) {
            e.printStackTrace();
            return "上传失败";
        }
    
        return "上传成功";
    }
    

    4)实现多文件上传方法

      相比单文件上传,多文件上传要先从request中获取文件列表,然后再对列表中的文件一一处理即可,处理策略同上述单文件上传方法

    @PostMapping("multiUpload")
    @ResponseBody String multiUpload(HttpServletRequest request) {
    
        List<MultipartFile> list = ((MultipartHttpServletRequest)request).getFiles("file");
    
        for(MultipartFile file : list) {
            //不可以上传空文件
            if(file.isEmpty()) {
                return "某文件为空,请选择文件后再上传";
            }
    
            String filename = file.getOriginalFilename();
            String suffix = filename.substring(filename.lastIndexOf("."));
            filename = UPLOAD_PATH + UUID.randomUUID() + suffix;
            File dest = new File(filename);
    
            //若文件已存在则不执行保存操作
            try {
                if(!dest.exists()) {
                    file.transferTo(dest);
                }
            } catch (Exception e) {
                e.printStackTrace();
                return "上传失败";
            }
        }
    
        return "上传成功";
    }
    

    5)实现文件下载方法

      要记得判断所需求的文件是否存在,并设置header

    @GetMapping("download")
    @ResponseBody
    public String download(HttpServletResponse response, String requestFilename) {
    
        File file = new File(DOWNLOAD_PATH + requestFilename);
        if (!file.exists()) {
            return "所访问的资源不存在";
        }
    
        try {
            FileInputStream fis = new FileInputStream(file);
            // 设置相关格式
            response.setContentType("application/force-download");
            // 设置下载后的文件名以及header
            response.addHeader("Content-disposition", "attachment;fileName=" + file.getName());
            OutputStream os = response.getOutputStream();
            byte[] buffer = new byte[DOWNLOAD_BUFFER_SIZE];
            int len = 0;
            while((len = fis.read(buffer)) != -1) {
                os.write(buffer, 0, len);
            }
            fis.close();
        } catch (Exception e) {
            e.printStackTrace();
            return "下载失败";
        }
    
        return "开始下载";
    }
    

    6)(可选)文件上传相关配置

      在application.properties或application.yml中可设置单个文件最大值max-file-size以及允许上传文件总大小max-requset-size,下以yml为例

    spring:
      servlet:
        multipart:
          max-file-size: 8MB
          max-requset-size: 16MB
    

    结果展示

      上传三张图片,分别使用单文件和多文件上传

    问题总结

    1. 要切记前端控件的name的值要和controller方法中参数的名称要一致。
    2. 要根据不同情况选择不同的命名策略,若无特殊要求,推荐UUID + 日期 + 后缀名的命名方式.
    3. 有时要上传静态资源文件,而且前端需要立刻使用上传后的文件,那么就需要实现SpringBoot热部署,该内容不在本篇博客的讨论范围,具体请移步SpringBoot实现热部署

    参考资料和链接

    SpringBoot5.2.7参考文档
    CSDN博客:SpringBoot的文件上传与下载

  • 相关阅读:
    leetcode297
    leetcode4
    leetcode23
    leetcode72
    leetcode239
    leetcode42
    leetcode128
    leetcode998
    SAP MM GR-based IV, 无GR不能IV?
    小科普:机器学习中的粒子群优化算法!
  • 原文地址:https://www.cnblogs.com/zwn-blog/p/13138171.html
Copyright © 2011-2022 走看看