Spring Boot之文件上傳、下載

前言

來(lái)啦老鐵!

筆者學(xué)習(xí)Spring Boot有一段時(shí)間了,附上Spring Boot系列學(xué)習(xí)文章,歡迎取閱、賜教:

  1. 5分鐘入手Spring Boot;
  2. Spring Boot數(shù)據(jù)庫(kù)交互之Spring Data JPA;
  3. Spring Boot數(shù)據(jù)庫(kù)交互之Mybatis;
  4. Spring Boot視圖技術(shù);
  5. Spring Boot之整合Swagger;
  6. Spring Boot之junit單元測(cè)試踩坑;
  7. 如何在Spring Boot中使用TestNG;
  8. Spring Boot之整合logback日志;
  9. Spring Boot之整合Spring Batch:批處理與任務(wù)調(diào)度;
  10. Spring Boot之整合Spring Security: 訪問(wèn)認(rèn)證;
  11. Spring Boot之整合Spring Security: 授權(quán)管理;
  12. Spring Boot之多數(shù)據(jù)庫(kù)源:極簡(jiǎn)方案;
  13. Spring Boot之使用MongoDB數(shù)據(jù)庫(kù)源;
  14. Spring Boot之多線程、異步:@Async;
  15. Spring Boot之前后端分離(一):Vue前端;
  16. Spring Boot之前后端分離(二):后端、前后端集成;
  17. Spring Boot之前后端分離(三):登錄、登出、頁(yè)面認(rèn)證;
  18. Spring Boot之面向切面編程:Spring AOP;
  19. Spring Boot之集成Redis(一):Redis初入門(mén);
  20. Spring Boot之集成Redis(二):集成Redis;
  21. Spring Boot之集成Redis(三):Spring Cache + Redis;

Redis挖了好大一個(gè)坑,肝了好幾天,Redis暫時(shí)就學(xué)到這吧,今天我們來(lái)學(xué)點(diǎn)輕松的!

最近換電腦,需要把舊電腦上的一些資料傳到新電腦,很多人是將舊電腦的資料上傳到云盤(pán),然后新電腦再?gòu)脑票P(pán)下載,這個(gè)過(guò)程本沒(méi)有問(wèn)題,我也經(jīng)常這么干,但問(wèn)題是云盤(pán)上傳文件的速度跟蝸牛爬一樣,于是有了今天這一說(shuō):

  • Spring Boot之文件上傳、下載

項(xiàng)目代碼已上傳Git Hub倉(cāng)庫(kù),歡迎取閱:

整體步驟

  1. 添加文件限制配置或編寫(xiě)文件限制配置類;
  2. 編寫(xiě)演示用文件上傳API;
  3. 編寫(xiě)演示用文件下載API;
  4. 文件上傳、下載演示;

1. 添加文件限制配置或編寫(xiě)文件限制配置類;

Spring Boot的默認(rèn)單次上傳文件的大小為10 MB,在沒(méi)有額外干預(yù)的情況下,上傳超過(guò)10 MB的文件,會(huì)有類似這樣的報(bào)錯(cuò):

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)

我們可以通過(guò)2種方式將這一限制擴(kuò)大。

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

這個(gè)方式很簡(jiǎn)單,比如我們想將文件限制放大到10 GB,只需要在application.properties文件中添加以下類似配置即可:

#單個(gè)文件大小限制
spring.servlet.multipart.max-file-size=10240MB
#單個(gè)請(qǐng)求,文件總大小限制
spring.servlet.multipart.max-request-size=10240MB

application.properties文件整體樣子:

server.port=8080
#單個(gè)文件大小限制
spring.servlet.multipart.max-file-size=10240MB
#單個(gè)請(qǐng)求,文件大小限制
spring.servlet.multipart.max-request-size=10240MB
#默認(rèn)文件上傳功能,文件保存的根目錄
file.upload.dir=E:\\Resource\\spring-boot-cloud\\
#默認(rèn)文件下載功能,文件保存的根目錄
file.download.dir=E:\\Resource\\spring-boot-cloud\\
2). 編寫(xiě)文件限制配置類方式;

這種方式也加單,新建config包,在包內(nèi)創(chuàng)建一個(gè)MultipartConfig.java類(名字不限),類中寫(xiě)入以下代碼:

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. 編寫(xiě)演示用文件上傳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. 編寫(xiě)演示用文件下載API;

為了系統(tǒng)學(xué)習(xí)文件上傳與下載,我又實(shí)現(xiàn)了一個(gè)文件下載的API。

新建FileDownloadController.java類,寫(xiě)入代碼:

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

上傳后:

上傳后

咱們來(lái)稍微解讀一下:

(1). 由于我要快速實(shí)現(xiàn)上傳接口,用于傳文件,所以我沒(méi)有做過(guò)多的驗(yàn)證和邏輯處理,關(guān)鍵代碼只有3行:

String fileName = file.getOriginalFilename();

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

即API拿到傳來(lái)的文件,拿其文件名,拼出服務(wù)器的文件路徑,保存就完事了!

(2). 我們可以在application.properties自定義一個(gè)默認(rèn)的上傳文件保存根目錄,然后用@Value注解引用進(jìn)項(xiàng)目,如:

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

(3). 文件上傳還是挺快的,經(jīng)試驗(yàn),2G的文件約600秒完成上傳,平均3.4 MB/s,況且我們省去了下載的動(dòng)作,相比于上傳到云盤(pán),再下載到新電腦的方式,簡(jiǎn)直是太快了!

(4). 上傳的速度應(yīng)該受我局域網(wǎng)設(shè)備(路由器)、局域網(wǎng)帶寬等的限制,但即使這樣,速度也是比云盤(pán)那種方式快多了,而且速度十分穩(wěn)定!

2). 文件下載:

(文件下載的功能是我們自己學(xué)習(xí)用的,與本次解決換電腦文件傳輸慢的問(wèn)題無(wú)關(guān)。)

由于我們寫(xiě)的是GET API,可在瀏覽器直接訪問(wèn)下載API,如:http://192.168.0.105:8080/api/file?fileName=Postman-win64-7.32.0-Setup.exe

文件下載

速度也是賊快哦!

至此,我們?cè)赟pring Boot項(xiàng)目中實(shí)現(xiàn)了文件的上傳、下載,整個(gè)過(guò)程非常輕松,可謂絲滑,讀者可自行擴(kuò)展,如批量文件上傳、下載等。

而經(jīng)過(guò)此次的學(xué)習(xí),我想我知道怎么做一個(gè)個(gè)人網(wǎng)盤(pán)了,你呢?

如果本文對(duì)您有幫助,麻煩點(diǎn)贊、關(guān)注!

謝謝!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容