首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Spring MVC 多文件上傳兩種實現方式深度對比:字節流 vs 解析器,效率相差百倍

     編輯:Java 相關知識

引言

Spring MVC 提供兩種多文件上傳路徑:一是手動以字節流讀寫,二是利用 CommonsMultipartResolver 解析器自動綁定。本文通過實測對比兩者在相同文件下的耗時差異,揭示效率懸殊的根本原因。

環境準備

  1. 依賴 JAR:commons-fileupload-1.2.0.jar、commons-io-1.4.0.jar
  2. Spring 配置 multipartResolver Bean,設定 maxUploadSize、maxInMemorySize
  3. web.xml 配置 DispatcherServlet 與 CharacterEncodingFilter

前端頁面:雙表單對比

頁面包含兩個獨立表單,分別提交至 /file/upload(字節流)與 /file/upload2(解析器),均支援動態新增/刪除文件輸入框。

後端 Controller 實現

方式一:字節流手動寫入 upload()

@RequestMapping("/upload")
public String addUser(@RequestParam("file") CommonsMultipartFile[] files, HttpServletRequest request) {
    for (CommonsMultipartFile file : files) {
        if (!file.isEmpty()) {
            long pre = System.currentTimeMillis();
            FileOutputStream os = new FileOutputStream("H:/" + new Date().getTime() + file.getOriginalFilename());
            FileInputStream in = (FileInputStream) file.getInputStream();
            int b;
            while ((b = in.read()) != -1) { os.write(b); } // 逐字節寫入
            os.close(); in.close();
            System.out.println("耗時:" + (System.currentTimeMillis() - pre) + "ms");
        }
    }
    return "/success";
}

方式二:解析器自動轉存 upload2()

@RequestMapping("/upload2")
public String upload2(HttpServletRequest request) throws IOException {
    CommonsMultipartResolver resolver = new CommonsMultipartResolver(request.getSession().getServletContext());
    if (resolver.isMultipart(request)) {
        MultipartHttpServletRequest multiRequest = (MultipartHttpServletRequest) request;
        Iterator<String> iter = multiRequest.getFileNames();
        while (iter.hasNext()) {
            long pre = System.currentTimeMillis();
            MultipartFile file = multiRequest.getFile(iter.next());
            if (file != null && StringUtils.isNotBlank(file.getOriginalFilename())) {
                file.transferTo(new File("H:/demoUpload" + file.getOriginalFilename())); // 一鍵轉存
            }
            System.out.println("耗時:" + (System.currentTimeMillis() - pre) + "ms");
        }
    }
    return "/success";
}

實測數據對比(三個相同文件)

方式文件 1文件 2文件 3
字節流逐字節寫入534 ms453 ms387 ms
解析器 transferTo2 ms1 ms2 ms

效率差異深度解析

  • 字節流方式:調用 in.read() / os.write(b) 逐字節複製,JNI 開銷極大,CPU 佔用高,磁盤 I/O 碎片化。
  • 解析器方式:MultipartFile.transferTo() 內部使用 FileChannel.transferTo 或 NIO 直接內存映射,實現零拷貝,系統調用極少,磁盤連續寫入。

最佳實踐建議

  1. 生產環境務必使用解析器方式,配合 maxInMemorySize 閾值自動切換內存/磁盤存儲。
  2. 大文件上傳建議啟用分片上傳與斷點續傳(如 Plupload、WebUploader)。
  3. 字節流僅適合教學演示或極簡場景,嚴禁用於高併發業務。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved