Spring Boot之文件上傳、下載

前言

來啦老鐵城榛!

筆者學習Spring Boot有一段時間了揪利,附上Spring Boot系列學習文章,歡迎取閱狠持、賜教:

  1. 5分鐘入手Spring Boot;
  2. Spring Boot數(shù)據(jù)庫交互之Spring Data JPA;
  3. Spring Boot數(shù)據(jù)庫交互之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之多數(shù)據(jù)庫源:極簡方案;
  13. Spring Boot之使用MongoDB數(shù)據(jù)庫源;
  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暫時就學到這吧得院,今天我們來學點輕松的!

最近換電腦章贞,需要把舊電腦上的一些資料傳到新電腦尿招,很多人是將舊電腦的資料上傳到云盤,然后新電腦再從云盤下載阱驾,這個過程本沒有問題,我也經(jīng)常這么干怪蔑,但問題是云盤上傳文件的速度跟蝸牛爬一樣里覆,于是有了今天這一說:

  • 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包梦皮,在包內(nèi)創(chuàng)建一個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覆旭;

為了系統(tǒng)學習文件上傳與下載退子,我又實現(xiàn)了一個文件下載的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). 由于我要快速實現(xiàn)上傳接口七兜,用于傳文件丸凭,所以我沒有做過多的驗證和邏輯處理,關鍵代碼只有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). 文件上傳還是挺快的涛菠,經(jīng)試驗莉御,2G的文件約600秒完成上傳,平均3.4 MB/s俗冻,況且我們省去了下載的動作礁叔,相比于上傳到云盤,再下載到新電腦的方式迄薄,簡直是太快了琅关!

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

2). 文件下載:

(文件下載的功能是我們自己學習用的都毒,與本次解決換電腦文件傳輸慢的問題無關。)

由于我們寫的是GET API碰缔,可在瀏覽器直接訪問下載API账劲,如:http://192.168.0.105:8080/api/file?fileName=Postman-win64-7.32.0-Setup.exe

文件下載

速度也是賊快哦!

至此,我們在Spring Boot項目中實現(xiàn)了文件的上傳瀑焦、下載腌且,整個過程非常輕松,可謂絲滑榛瓮,讀者可自行擴展铺董,如批量文件上傳、下載等禀晓。

而經(jīng)過此次的學習精续,我想我知道怎么做一個個人網(wǎng)盤了,你呢粹懒?

如果本文對您有幫助重付,麻煩點贊、關注凫乖!

謝謝确垫!

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市帽芽,隨后出現(xiàn)的幾起案子删掀,更是在濱河造成了極大的恐慌,老刑警劉巖导街,帶你破解...
    沈念sama閱讀 211,290評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件爬迟,死亡現(xiàn)場離奇詭異,居然都是意外死亡菊匿,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,107評論 2 385
  • 文/潘曉璐 我一進店門计福,熙熙樓的掌柜王于貴愁眉苦臉地迎上來跌捆,“玉大人,你說我怎么就攤上這事象颖∨搴瘢” “怎么了?”我有些...
    開封第一講書人閱讀 156,872評論 0 347
  • 文/不壞的土叔 我叫張陵说订,是天一觀的道長抄瓦。 經(jīng)常有香客問我,道長陶冷,這世上最難降的妖魔是什么钙姊? 我笑而不...
    開封第一講書人閱讀 56,415評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮埂伦,結果婚禮上煞额,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好膊毁,可當我...
    茶點故事閱讀 65,453評論 6 385
  • 文/花漫 我一把揭開白布胀莹。 她就那樣靜靜地躺著,像睡著了一般婚温。 火紅的嫁衣襯著肌膚如雪描焰。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,784評論 1 290
  • 那天栅螟,我揣著相機與錄音荆秦,去河邊找鬼。 笑死嵌巷,一個胖子當著我的面吹牛萄凤,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播搪哪,決...
    沈念sama閱讀 38,927評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼靡努,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了晓折?” 一聲冷哼從身側響起惑朦,我...
    開封第一講書人閱讀 37,691評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎漓概,沒想到半個月后漾月,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,137評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡胃珍,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,472評論 2 326
  • 正文 我和宋清朗相戀三年梁肿,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片觅彰。...
    茶點故事閱讀 38,622評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡吩蔑,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出填抬,到底是詐尸還是另有隱情烛芬,我是刑警寧澤,帶...
    沈念sama閱讀 34,289評論 4 329
  • 正文 年R本政府宣布飒责,位于F島的核電站赘娄,受9級特大地震影響,放射性物質發(fā)生泄漏宏蛉。R本人自食惡果不足惜遣臼,卻給世界環(huán)境...
    茶點故事閱讀 39,887評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望拾并。 院中可真熱鬧暑诸,春花似錦蚌讼、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,741評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至西采,卻和暖如春凰萨,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背械馆。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工胖眷, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人霹崎。 一個月前我還...
    沈念sama閱讀 46,316評論 2 360
  • 正文 我出身青樓珊搀,卻偏偏與公主長得像,于是被迫代替她去往敵國和親尾菇。 傳聞我的和親對象是個殘疾皇子境析,可洞房花燭夜當晚...
    茶點故事閱讀 43,490評論 2 348