SpringBoot文件上传与下载

理论介绍

Java Web的开发之中,我们不可避免会有文件的上传与下载的需求,文件的上传与下载,在Spring MVC的时代文件的上传与下载比较配置比较复杂,或者说在Spring MVC的时代开发的配置都比较复杂,随着Spring Boot的普及,现在我们我们的开发已经比较简单,对于上传与下载,需要注意的就是MultipartFile类型与HttpServletResponse请求,这两个是比较重要的地方。

文件上传的时候,使用MultipartFile来包装上传的文件的信息,MultipartFile是一个接口,我们在Http请求之中使用的具体的子类是StandardMultipartFile,其中封装了文件名称,文件类型,文件大小,内容,然后提供了一个文件复制的方法,如下:

SpringBoot文件上传与下载

文件下载,主要就是在客户端发送一个下载的请求,然后把文件从浏览器之中下载下来,这个过程之中,我们要找到请求的文件的位置,然后把它作为输入,输出到我们的输出流之中,此处就要使用到我们上述的HttpServletResponse响应对象,把请求到的文件的内容输出到响应的输出流之中即可。当然需要在输出之前设置响应的类型,header信息,关键的代码如下:

1response.setContentType("application/octet-stream");
2response.setHeader("Content-Disposition""attachment;filename=" + fileName);

代码实战

事先配置

我们要上传文件,就要开启上传,然后对于请求的大小和上传的文件的大小要有一个设置,同时,上传时还必须给一个存储的路径,这样我们就可以把上传的文件,存储到我们指定的位置了,具体的配置如下:

1# 开启上传和下载
2spring.servlet.multipart.enabled=true
3# 最大的文件大小
4spring.servlet.multipart.max-file-size=20MB
5# 单次最大请求大小
6spring.servlet.multipart.max-request-size=20MB
7
8# 自定义的上传文件存放路径
9file.upload.dir=d:/test

需要说明的是,开启上传默认是true,如果不想开启这个功能,我们可以设置false关闭上传功能,自定义的上传文件路径,这个字段是自定义的,没有标准的字段,也可以不配置,直接在代码里面设置,但是这样会显得混乱,不利于我们开发。

  1@RestController
2@RequestMapping("file")
3@Slf4j
4public class FileController {
5    @Value("${file.upload.dir}")
6    private String uploadFilePath;
7
8    @PostMapping("/uploadFile")
9    public String fileUpload(@RequestParam("file") MultipartFile file) throws JSONException {
10        JSONObject result = new JSONObject();
11        if (file.isEmpty()) {
12            result.put("error""空文件!");
13            return result.toString();
14        }
15        // 文件名
16        String fileName = file.getOriginalFilename();
17        String suffixName = fileName.substring(fileName.lastIndexOf("."));
18        log.info("上传文件名称为:{}, 后缀名为:{}!", fileName, suffixName);
19
20        File fileTempObj = new File(uploadFilePath + "/" + fileName);
21        // 检测目录是否存在
22        if (!fileTempObj.getParentFile().exists()) {
23            fileTempObj.getParentFile().mkdirs();
24        }
25        // 使用文件名称检测文件是否已经存在
26        if (fileTempObj.exists()) {
27            result.put("error""文件已经存在!");
28            return result.toString();
29        }
30
31        try {
32            // 写入文件:方式1
33            // file.transferTo(fileTempObj);
34            // 写入文件:方式2
35            FileUtil.writeBytes(file.getBytes(), fileTempObj);
36        } catch (Exception e) {
37            log.error("发生错误: {}", e);
38            result.put("error", e.getMessage());
39            return result.toString();
40        }
41
42        result.put("success""文件上传成功!");
43        return result.toString();
44    }
45
46    /**
47     * 多个文件上传
48     *
49     * @param files
50     * @return
51     * @throws JSONException
52     */

53    @ResponseBody
54    @PostMapping("/uploadFiles")
55    public String fileUploads(@RequestParam("files") MultipartFile files[]) throws JSONException {
56        JSONObject result = new JSONObject();
57
58        for (int i = 0; i < files.length; i++) {
59            String fileName = files[i].getOriginalFilename();
60            File dest = new File(uploadFilePath + '/' + fileName);
61            if (!dest.getParentFile().exists()) {
62                dest.getParentFile().mkdirs();
63            }
64            try {
65                files[i].transferTo(dest);
66            } catch (Exception e) {
67                log.error("发生错误: {}", e);
68                result.put("error", e.getMessage());
69                return result.toString();
70            }
71        }
72        result.put("success""文件上传成功!");
73        return result.toString();
74    }
75
76
77    // 下载到了默认的位置
78    @ResponseBody
79    @GetMapping("/downloadFile")
80    public String fileDownload(HttpServletResponse response, @RequestParam("fileName") String fileName) throws JSONException, IOException {
81        JSONObject result = new JSONObject();
82
83        File file = new File(uploadFilePath + '/' + fileName);
84        if (!file.exists()) {
85            result.put("error""下载文件不存在!");
86            return result.toString();
87        }
88
89        response.reset();
90        response.setContentType("application/octet-stream");
91        response.setCharacterEncoding("utf-8");
92        response.setContentLength((int) file.length());
93        response.setHeader("Content-Disposition""attachment;filename=" + fileName);
94
95        // 原生的方式
96        // try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));) {
97        //     byte[] buff = new byte[1024];
98        //     OutputStream os = response.getOutputStream();
99        //     int i = 0;
100        //     while ((i = bis.read(buff)) != -1) {
101        //         os.write(buff, 0, i);
102        //         os.flush();
103        //     }
104        // } catch (IOException e) {
105        //     log.error("发生错误: {}", e);
106        //     result.put("error", e.getMessage());
107        //     return result.toString();
108        // }
109        // 简单方式: 方式1
110        // byte[] bytes = FileCopyUtils.copyToByteArray(file);
111        // 简单方式: 方式2
112        byte[] readBytes = FileUtil.readBytes(file);
113        OutputStream os = response.getOutputStream();
114        os.write(readBytes);
115        result.put("success""下载成功!");
116        return result.toString();
117    }
118
119}

在上面的上传文件之中,写入文件方式1和写入文件方式2的作用是相同的,前者是使用的StandardMultipartFiletransferTo方法,把该文件,传送到我们指定的位置;第二种方法,是先取到这个文件的内容,单位是Byte,然后再去写入,有个限制就是这个文件的大小不能大于Integer.MAX_VALUE,也就是2GB,这个对于普通的需求完全够用了,如果想一次性上传这么大的文件,然后一次性获取内容字节,然后再去写入,那这个时候我们就需要使用大文件上传的方式了,必须要先对文件分片,然后一片一片写入对应片的内容即可,这个在后续会讲解,此处的第二种方式,主要是要个给大家介绍一个工具,就是Hutool,里面有各种好用的Util工具,可以帮助我们快速开发,我们就不需要自己写各种Util了,别人的轮子直接使用,除非没有满足我们需求的,我们自己实现,这样可以加快我们开发的效率。

下载文件的代码之中也提供了不同的方式,前者是Spring自带的工具,后者是Hutool,作用是相同的。

单独的接口的测试,可以使用postman,如果不想使用这种方式,可以添加前端的页面,我的项目里面完成了前后端的交互,页面效果如下,前端UI是Bootstrap,多个文件的上传使用了Bootstrap Fileinput控件,项目仓库:上传与下载项目地址。

SpringBoot文件上传与下载

SpringBoot文件上传与下载


本篇文章来源于微信公众号: 疾风小虎牙

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/13930.html

(0)
小半的头像小半

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!