阅读 90

Spring Boot之文件上传、下载

前言

来啦老铁!

笔者学习Spring Boot有一段时间了,附上Spring Boot系列学习文章,欢迎取阅、赐教:

  1. 5分钟入手Spring Boot;
  2. Spring Boot数据库交互之Spring Data JPA;
  3. Spring Boot数据库交互之Mybatis;
  4. Spring Boot视图技术;
  5. Spring Boot之整合Swagger;
  6. Spring Boot之junit单元测试踩坑;
  7. 如何在Spring Boot中使用TestNG;
  8. Spring Boot之整合logback日志;
  9. Spring Boot之整合Spring Batch:批处理与任务调度;
  10. Spring Boot之整合Spring Security: 访问认证;
  11. Spring Boot之整合Spring Security: 授权管理;
  12. Spring Boot之多数据库源:极简方案;
  13. Spring Boot之使用MongoDB数据库源;
  14. Spring Boot之多线程、异步:@Async;
  15. Spring Boot之前后端分离(一):Vue前端;
  16. Spring Boot之前后端分离(二):后端、前后端集成;
  17. Spring Boot之前后端分离(三):登录、登出、页面认证;
  18. Spring Boot之面向切面编程:Spring AOP;
  19. Spring Boot之集成Redis(一):Redis初入门;
  20. Spring Boot之集成Redis(二):集成Redis;
  21. Spring Boot之集成Redis(三):Spring Cache + Redis;

Redis挖了好大一个坑,肝了好几天,Redis暂时就学到这吧,今天我们来学点轻松的!

最近换电脑,需要把旧电脑上的一些资料传到新电脑,很多人是将旧电脑的资料上传到云盘,然后新电脑再从云盘下载,这个过程本没有问题,我也经常这么干,但问题是云盘上传文件的速度跟蜗牛爬一样,于是有了今天这一说:

  • Spring Boot之文件上传、下载

项目代码已上传Git Hub仓库,欢迎取阅:

整体步骤

  1. 添加文件限制配置或编写文件限制配置类;
  2. 编写演示用文件上传API;
  3. 编写演示用文件下载API;
  4. 文件上传、下载演示;

1. 添加文件限制配置或编写文件限制配置类;

Spring Boot的默认单次上传文件的大小为10 MB,在没有额外干预的情况下,上传超过10 MB的文件,会有类似这样的报错:

org.apache.tomcat.util.http.fileupload.impl.FileSizeLimitExceededException: The field file exceeds its maximum permitted size of 1048576 bytes.
    at org.apache.tomcat.util.http.fileupload.impl.FileItemStreamImpl$1.raiseError(FileItemStreamImpl.java:114)
    at org.apache.tomcat.util.http.fileupload.util.LimitedInputStream.checkLimit(LimitedInputStream.java:76)
    at org.apache.tomcat.util.http.fileupload.util.LimitedInputStream.read(LimitedInputStream.java:135)
    at java.io.FilterInputStream.read(FilterInputStream.java:107)
    at org.apache.tomcat.util.http.fileupload.util.Streams.copy(Streams.java:98)
    at org.apache.tomcat.util.http.fileupload.FileUploadBase.parseRequest(FileUploadBase.java:291)
    at org.apache.catalina.connector.Request.parseParts(Request.java:2869)
    at org.apache.catalina.connector.Request.getParts(Request.java:2771)
    at org.apache.catalina.connector.RequestFacade.getParts(RequestFacade.java:1098)

我们可以通过2种方式将这一限制扩大。

1). 添加文件限制配置方式;

这个方式很简单,比如我们想将文件限制放大到10 GB,只需要在application.properties文件中添加以下类似配置即可:

#单个文件大小限制
spring.servlet.multipart.max-file-size=10240MB
#单个请求,文件总大小限制
spring.servlet.multipart.max-request-size=10240MB

application.properties文件整体样子:

server.port=8080
#单个文件大小限制
spring.servlet.multipart.max-file-size=10240MB
#单个请求,文件大小限制
spring.servlet.multipart.max-request-size=10240MB
#默认文件上传功能,文件保存的根目录
file.upload.dir=E:\\Resource\\spring-boot-cloud\\
#默认文件下载功能,文件保存的根目录
file.download.dir=E:\\Resource\\spring-boot-cloud\\
2). 编写文件限制配置类方式;

这种方式也加单,新建config包,在包内创建一个MultipartConfig.java类(名字不限),类中写入以下代码:

package com.github.dylanz666.config;

import org.springframework.boot.web.servlet.MultipartConfigFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.unit.DataSize;

import javax.servlet.MultipartConfigElement;


/**
 * @author : dylanz
 * @since : 11/02/2020
 */

@Configuration
public class MultipartConfig {
    @Bean
    public MultipartConfigElement multipartConfigElement() {
        MultipartConfigFactory multipartConfigFactory = new MultipartConfigFactory();

        multipartConfigFactory.setMaxFileSize(DataSize.parse("10240MB"));
        multipartConfigFactory.setMaxRequestSize(DataSize.parse("10240MB"));

        return multipartConfigFactory.createMultipartConfig();
    }
}

2种方式效果一样,任君选择!

2. 编写演示用文件上传API;

package com.github.dylanz666.controller;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;

/**
 * @author : dylanz
 * @since : 11/02/2020
 */
@RestController
@RequestMapping("/api")
public class FileUploadController {
    @Value(value = "${file.upload.dir}")
    private String rootPath;

    @GetMapping("/upload/ping")
    public String ping() {
        return "success";
    }

    @PostMapping("/file")
    public Boolean upload(@RequestParam("file") MultipartFile file) {
        try {
            String fileName = file.getOriginalFilename();
            assert fileName != null;
            System.out.println(fileName);

            File dest = new File(rootPath, fileName);
            file.transferTo(dest);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }
}

3. 编写演示用文件下载API;

为了系统学习文件上传与下载,我又实现了一个文件下载的API。

新建FileDownloadController.java类,写入代码:

package com.github.dylanz666.controller;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletResponse;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.util.Objects;

/**
 * @author : dylanz
 * @since : 11/08/2020
 */
@RestController
@RequestMapping("/api")
public class FileDownloadController {
    @Value(value = "${file.download.dir}")
    private String rootPath;

    private FileInputStream fis = null;
    private BufferedInputStream bis = null;

    @GetMapping("/download/ping")
    public String ping() {
        return "success";
    }

    @GetMapping("/file")
    public String download(@RequestParam String fileName) {
        try {
            File file = new File(rootPath, fileName);

            HttpServletResponse response = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getResponse();
            assert response != null;
            response.setContentType("application/force-download");
            response.setCharacterEncoding("UTF-8");
            response.setHeader("Content-Disposition", "attachment;fileName=" + URLEncoder.encode(fileName, "UTF-8"));

            if (file.exists()) {
                byte[] buffer = new byte[1024];
                fis = new FileInputStream(file);
                bis = new BufferedInputStream(fis);
                OutputStream os = response.getOutputStream();

                int i = bis.read(buffer);
                while (i != -1) {
                    os.write(buffer, 0, i);
                    i = bis.read(buffer);
                }
            }
            return "success";
        } catch (Exception e) {
            e.printStackTrace();
            return "fail";
        } finally {
            try {
                bis.close();
                fis.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

4. 文件上传、下载演示;

1). 文件上传:

上传前:

上传前

上传:

上传 1
上传 2

上传后:

上传后

咱们来稍微解读一下:

(1). 由于我要快速实现上传接口,用于传文件,所以我没有做过多的验证和逻辑处理,关键代码只有3行:

String fileName = file.getOriginalFilename();

File dest = new File(rootPath + fileName);
file.transferTo(dest);

即API拿到传来的文件,拿其文件名,拼出服务器的文件路径,保存就完事了!

(2). 我们可以在application.properties自定义一个默认的上传文件保存根目录,然后用@Value注解引用进项目,如:

@Value(value = "${file.upload.dir}")
private String rootPath;

(3). 文件上传还是挺快的,经试验,2G的文件约600秒完成上传,平均3.4 MB/s,况且我们省去了下载的动作,相比于上传到云盘,再下载到新电脑的方式,简直是太快了!

(4). 上传的速度应该受我局域网设备(路由器)、局域网带宽等的限制,但即使这样,速度也是比云盘那种方式快多了,而且速度十分稳定!

2). 文件下载:

(文件下载的功能是我们自己学习用的,与本次解决换电脑文件传输慢的问题无关。)

由于我们写的是GET API,可在浏览器直接访问下载API,如:http://192.168.0.105:8080/api/file?fileName=Postman-win64-7.32.0-Setup.exe

文件下载

速度也是贼快哦!

至此,我们在Spring Boot项目中实现了文件的上传、下载,整个过程非常轻松,可谓丝滑,读者可自行扩展,如批量文件上传、下载等。

而经过此次的学习,我想我知道怎么做一个个人网盘了,你呢?

如果本文对您有帮助,麻烦点赞、关注!

谢谢!

作者:狄仁杰666

原文链接:https://www.jianshu.com/p/d2dd27bbd1c5

文章分类
后端
版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
相关推荐