spring boot 三兩行代碼實(shí)現(xiàn)文件的上傳和下載

本示例記錄Spring Boot 2.x中文件的上傳,整個(gè)上傳邏輯只有兩三行代碼。

一、文件的上傳

@RequestMapping("files")
@RestController
public class FileController {

    // 確定存儲(chǔ)文件的目錄
    private String path = "d:" + File.separator + "uploader";

    @PostMapping
    public Map<String, Object> upload(@RequestParam("file") MultipartFile file)
            throws IllegalStateException, IOException {
        // 獲取原始文件名
        String filename = file.getOriginalFilename();
        // 構(gòu)建保存目標(biāo)
        File target = new File(path + File.separator + filename);
        // 將文件轉(zhuǎn)移到指定目錄
        file.transferTo(target);
        // 構(gòu)建響應(yīng)
        Map<String, Object> response = new HashMap<>();
        response.put("target", target.getAbsolutePath());
        return response;
    }

    @PostConstruct
    public void initStorage() {
        File target = new File(path);
        if (!target.exists()) {
            if (target.mkdirs()) {
                System.out.println("文件存儲(chǔ)目錄創(chuàng)建成功。");
            } else {
                System.err.println("文件存儲(chǔ)目錄創(chuàng)建失敗。");
            }
        }
    }
}

代碼解析:
基于Restful風(fēng)格構(gòu)建的文件上傳邏輯。文件上傳的邏輯寫在upload方法中。

  • 使用屬性path存儲(chǔ)文件的保存位置,這個(gè)可以放在配置文件中。
  • MultipartFile是Spring提供的,解析multipart request后,對(duì)于請(qǐng)求中的文件的包裝。它提供了一些常用的方法來操作文件。包括獲取文件名,獲取文件長(zhǎng)度,獲取原始文件名等。
  • 使用MultipartFile.transferTo(target)將文件保存到指定目標(biāo)位置。
  • initStorage方法用于在系統(tǒng)啟動(dòng)時(shí),初始化文件存儲(chǔ)目錄,這里沒有考慮到各種異常情況。上傳的關(guān)鍵不在這里。
  • 關(guān)于異常處理:在上傳的邏輯中沒有處理各種異常,轉(zhuǎn)而交由Spring boot的統(tǒng)一異常處理邏輯來處理異常。
    測(cè)試:
    使用postman進(jìn)行一個(gè)簡(jiǎn)單的測(cè)試
    測(cè)試一.png
  • 注意輸入正確的地址
  • 方法選擇post
  • body選擇form-data
  • 給定一個(gè)名稱為file參數(shù)(和controller中的RequestParam對(duì)應(yīng)),value選擇一個(gè)文件。
    可能發(fā)生的錯(cuò)誤
  • Maximum upload size exceeded。這時(shí)由于上傳文件的大小超過了服務(wù)器可以接受的上限導(dǎo)致的。
    可以通過配置服務(wù)器請(qǐng)求大小限制來解決,修改application.yml,添加如下配置
spring:
  servlet:
    multipart:
      max-file-size: 200MB
      max-request-size: 200MB
  • spring.servlet.multipart.max-file-size #用于控制multipart request中,單個(gè)文件的大小
  • spring.servlet.multipart.max-request-size #用于控制multipart request中,整體請(qǐng)求的大小(一個(gè)上傳請(qǐng)求可以添加多個(gè)文件,所有文件的大小總和不能超過該數(shù)值)。

二、文件的下載

繼續(xù)在controller中添加下載代碼邏輯

    @GetMapping("{filename}")
    public ResponseEntity<InputStreamSource> download(@PathVariable("filename") String filename) {
        // 構(gòu)建下載路徑
        File target = new File(path + File.separator + filename);
        // 構(gòu)建響應(yīng)體
        if (target.exists()) {
            FileSystemResource resource = new FileSystemResource(target);
            return ResponseEntity.ok()
                    // 指定文件的contentType
                    .contentType(MediaType.APPLICATION_OCTET_STREAM)
                    .body(resource);
        } else {
            // 如果文件不存在,返回404響應(yīng)
            return ResponseEntity.notFound().build();
        }
    }

代碼解析:

  • 使用restful風(fēng)格的api
  • 使用ResponseEntity<InputStreamSource>作為響應(yīng)。
  • InputStreamSource是Spring提供的,它能簡(jiǎn)化對(duì)于使用InputStream作為響應(yīng)時(shí)的編程。網(wǎng)上很多其它文章都是通過獲取response中的outputStream,然后向outputStream中寫入數(shù)據(jù)來實(shí)現(xiàn)下載,稍顯復(fù)雜。
  • FileSystemResource是InputStreamSource的一個(gè)實(shí)現(xiàn)。它使用nio來實(shí)現(xiàn)數(shù)據(jù)的復(fù)制,能夠顯著的減少在文件下載時(shí)CPU的使用量(具體實(shí)現(xiàn)在不同的平臺(tái)中會(huì)有所差別,相關(guān)概念參考 《零復(fù)制》)。

小結(jié)

這應(yīng)該是Spring boot中最簡(jiǎn)單的文件上傳和下載功能了,而且從理論上來將,性能也是比較優(yōu)秀的(利用了nio)。但功能還是相對(duì)簡(jiǎn)單。接下來還會(huì)實(shí)現(xiàn)文件的斷點(diǎn)續(xù)傳,視頻的拖動(dòng)播放等功能。
示例參考 https://github.com/ldwqh0/file-uploader.git

相關(guān)文章
spring boot 三兩行代碼實(shí)現(xiàn)文件的上傳和下載
spring boot 文件下載的預(yù)覽和緩存
Spring配合Nginx實(shí)現(xià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)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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