精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

告別卡頓!SpringBoot 大文件上傳最佳實踐:分片+并發+秒傳全搞定

開發 后端
通過 Spring Boot 構建的分片上傳系統,不僅解決了大文件傳輸過程中的性能瓶頸,還提供了斷點續傳、上傳加速、失敗重試、安全校驗等完整機制。結合前端優化與后端云服務整合,可無縫部署到生產環境,廣泛適用于音視頻平臺、文檔系統、網盤等多種場景。

在現代 Web 系統中,尤其是涉及視頻、圖像、大型文檔管理等場景時,大文件上傳常常成為性能瓶頸。傳統上傳方式面對 100MB 以上的大文件時常出現超時、資源溢出、上傳失敗等問題。為了提升上傳效率與穩定性,我們構建了一套基于 Spring Boot 的高性能文件分片上傳系統,結合斷點續傳、并發上傳、安全驗證與 MinIO 云存儲,打造出企業級健壯傳輸方案。

為什么要進行文件分片上傳?

在上傳大于 100MB 的文件時,傳統上傳方式暴露出以下問題:

  • 傳輸不穩定:長時間傳輸極易超時或被網絡波動中斷
  • 資源壓力大:服務器需要一次性讀取整個文件,造成內存暴漲
  • 失敗代價高:上傳中斷后無法恢復,只能重新上傳整個文件

通過將大文件拆分為多個較小的塊,可以顯著優化上述問題:

優勢

說明

斷點續傳

支持中斷后從上次上傳點恢復

并發加速

多個分塊同時上傳,提升速度

降低服務器壓力

每個分塊獨立上傳,降低內存占用

分片上傳的原理

分片上傳核心思想如下:

  1. 將大文件在前端分割為若干固定大小的塊
  2. 后端接受每個分塊,并臨時存儲
  3. 上傳完成后,后端將所有分塊按順序合并為最終文件
  4. 合并成功后清理臨時分塊

項目結構設計

/upload-platform
├── src/
│   ├── main/
│   │   ├── java/com/icoderoad/upload/
│   │   │   ├── controller/ChunkUploadController.java       # 上傳控制器
│   │   │   ├── service/FileMergeService.java               # 文件合并服務
│   │   │   ├── config/MinioConfig.java                     # MinIO配置
│   │   │   └── UploadPlatformApplication.java              # 主程序
│   │   ├── resources/
│   │   │   ├── templates/
│   │   │   │   └── upload.html                             # 上傳頁面(Thymeleaf)
│   │   │   ├── static/
│   │   │   │   ├── css/bootstrap.min.css
│   │   │   │   └── js/upload.js                            # 分片上傳邏輯
│   │   │   └── application.yml                             # 配置文件
├── pom.xml

后端實現

pom.xml

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>commons-io</groupId>
        <artifactId>commons-io</artifactId>
        <version>2.11.0</version>
    </dependency>
    <dependency>
        <groupId>io.minio</groupId>
        <artifactId>minio</artifactId>
        <version>8.5.3</version>
    </dependency>
</dependencies>

application.yml

server:
  port: 8080


spring:
  servlet:
    multipart:
      max-file-size: 100MB
      max-request-size: 100MB

MinioConfig.java

package com.icoderoad.upload.config;


import io.minio.MinioClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;


@Configuration
public class MinioConfig {
    @Bean
    public MinioClient minioClient() {
        return MinioClient.builder()
                .endpoint("http://localhost:9000")
                .credentials("minio-access", "minio-secret")
                .build();
    }
}

ChunkUploadController.java

package com.icoderoad.upload.controller;


import org.apache.commons.io.FileUtils;
import org.springframework.http.*;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;


import java.io.*;
import java.nio.file.*;
import java.util.*;
import java.util.stream.Collectors;


@RestController
@RequestMapping("/upload")
public class ChunkUploadController {


    private static final String CHUNK_DIR = "/tmp/upload/chunks/";
    private static final String FINAL_DIR = "/tmp/upload/final/";


    @PostMapping("/init")
    public ResponseEntity<String> initUpload(@RequestParam String fileName, @RequestParam String fileMd5) {
        String uploadId = UUID.randomUUID().toString();
        Path path = Paths.get(CHUNK_DIR, fileMd5 + "_" + uploadId);
        try {
            Files.createDirectories(path);
        } catch (IOException e) {
            return ResponseEntity.status(500).body("初始化失敗");
        }
        return ResponseEntity.ok(uploadId);
    }


    @PostMapping("/chunk")
    public ResponseEntity<String> uploadChunk(@RequestParam MultipartFile chunk,
                                              @RequestParam String uploadId,
                                              @RequestParam String fileMd5,
                                              @RequestParam Integer index) {
        String chunkName = "chunk_" + index + ".tmp";
        Path target = Paths.get(CHUNK_DIR, fileMd5 + "_" + uploadId, chunkName);
        try {
            chunk.transferTo(target);
            return ResponseEntity.ok("分塊成功");
        } catch (IOException e) {
            return ResponseEntity.status(500).body("保存失敗");
        }
    }


    @PostMapping("/merge")
    public ResponseEntity<String> mergeChunks(@RequestParam String fileName,
                                              @RequestParam String uploadId,
                                              @RequestParam String fileMd5) {
        File chunkFolder = new File(CHUNK_DIR + fileMd5 + "_" + uploadId);
        File[] chunkFiles = chunkFolder.listFiles();


        if (chunkFiles == null || chunkFiles.length == 0) {
            return ResponseEntity.badRequest().body("未找到分塊");
        }


        Arrays.sort(chunkFiles, Comparator.comparingInt(f ->
                Integer.parseInt(f.getName().replace("chunk_", "").replace(".tmp", ""))));


        Path finalPath = Paths.get(FINAL_DIR, fileName);
        try (BufferedOutputStream output = new BufferedOutputStream(Files.newOutputStream(finalPath))) {
            for (File chunk : chunkFiles) {
                Files.copy(chunk.toPath(), output);
            }
            FileUtils.deleteDirectory(chunkFolder);
            return ResponseEntity.ok("上傳完成:" + finalPath);
        } catch (IOException e) {
            return ResponseEntity.status(500).body("合并失敗:" + e.getMessage());
        }
    }


    @GetMapping("/check/{fileMd5}/{uploadId}")
    public ResponseEntity<List<Integer>> checkChunks(@PathVariable String fileMd5, @PathVariable String uploadId) {
        Path chunkPath = Paths.get(CHUNK_DIR, fileMd5 + "_" + uploadId);
        if (!Files.exists(chunkPath)) return ResponseEntity.ok(Collections.emptyList());


        try {
            List<Integer> indices = Files.list(chunkPath)
                    .map(p -> p.getFileName().toString())
                    .map(name -> name.replace("chunk_", "").replace(".tmp", ""))
                    .map(Integer::parseInt)
                    .collect(Collectors.toList());
            return ResponseEntity.ok(indices);
        } catch (IOException e) {
            return ResponseEntity.status(500).body(Collections.emptyList());
        }
    }
}

前端頁面(upload.html)

路徑:resources/templates/upload.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <title>分片上傳演示</title>
    <link rel="stylesheet" href="/css/bootstrap.min.css"/>
</head>
<body class="p-4">
    <h3>分片上傳</h3>
    <input type="file" id="fileInput" class="form-control mb-2"/>
    <div class="progress mb-2">
        <div class="progress-bar" id="progressBar" role="progressbar" style="width: 0%;">0%</div>
    </div>
    <button class="btn btn-primary" onclick="startUpload()">開始上傳</button>


    <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
    <script src="/js/upload.js"></script>
</body>
</html>

JS 邏輯(upload.js)

路徑:resources/static/js/upload.js

const CHUNK_SIZE = 5 * 1024 * 1024;


async function calculateFileMd5(file) {
    // 簡化處理:用文件名和大小模擬唯一標識(實際應用使用 SparkMD5)
    return `${file.name}-${file.size}`;
}


function splitFile(file) {
    const chunks = [];
    const count = Math.ceil(file.size / CHUNK_SIZE);
    for (let i = 0; i < count; i++) {
        chunks.push(file.slice(i * CHUNK_SIZE, (i + 1) * CHUNK_SIZE));
    }
    return chunks;
}


function updateProgress(percent) {
    const bar = document.getElementById("progressBar");
    bar.style.width = `${percent}%`;
    bar.textContent = `${percent}%`;
}


async function startUpload() {
    const file = document.getElementById("fileInput").files[0];
    if (!file) return alert("請選擇文件");


    const fileMd5 = await calculateFileMd5(file);
    const { data: uploadId } = await axios.post("/upload/init", {
        fileName: file.name,
        fileMd5
    });


    const chunks = splitFile(file);
    const uploadedChunks = (await axios.get(`/upload/check/${fileMd5}/${uploadId}`)).data;
    let uploaded = uploadedChunks.length;


    await Promise.all(chunks.map(async (chunk, index) => {
        if (uploadedChunks.includes(index)) return;


        const formData = new FormData();
        formData.append("chunk", chunk);
        formData.append("index", index);
        formData.append("uploadId", uploadId);
        formData.append("fileMd5", fileMd5);


        await axios.post("/upload/chunk", formData, {
            onUploadProgress: () => {
                uploaded++;
                const percent = ((uploaded / chunks.length) * 100).toFixed(1);
                updateProgress(percent);
            }
        });
    }));


    await axios.post("/upload/merge", {
        fileName: file.name,
        uploadId,
        fileMd5
    });


    alert("上傳完成!");
}

總結建議

  • 適配分片大小

局域網:10MB ~ 20MB

移動網絡:1MB ~ 5MB

廣域網:500KB ~ 1MB

  • 定時清理策略
@Scheduled(cron = "0 0 3 * * ?") // 每天凌晨3點清理臨時目錄
public void cleanChunks() {
    FileUtils.deleteQuietly(new File("/tmp/upload/chunks/"));
}
  • 安全驗證建議

使用 HMAC + 文件摘要校驗簽名完整性

上傳前預計算 MD5 或 SHA256

  • 云存儲集成推薦
  • MinIO / OSS / COS / S3 等對象存儲平臺
  • 可直接分片上傳至對象存儲,節省本地合并

結語

通過 Spring Boot 構建的分片上傳系統,不僅解決了大文件傳輸過程中的性能瓶頸,還提供了斷點續傳、上傳加速、失敗重試、安全校驗等完整機制。結合前端優化與后端云服務整合,可無縫部署到生產環境,廣泛適用于音視頻平臺、文檔系統、網盤等多種場景。

如果你正在構建涉及大文件上傳的系統,這套方案將為你帶來更穩定、更高效的體驗!

責任編輯:武曉燕 來源: 路條編程
相關推薦

2021-01-15 11:40:44

文件Java秒傳

2022-06-15 09:01:45

大文件秒傳分片上傳

2024-11-12 09:54:23

2022-08-05 08:40:37

架構

2025-04-10 08:03:31

Spring系統

2024-07-02 10:18:18

2025-07-03 07:06:56

2025-07-02 00:00:00

2025-06-27 02:32:00

2021-06-01 05:15:36

JavaScript 前端大文件并發上傳

2015-05-05 10:08:15

Android谷歌Sky

2022-06-13 14:06:33

大文件上傳前端

2009-11-16 11:41:19

PHP上傳大文件

2020-05-03 13:53:08

WiFi信號無線網絡

2020-04-02 20:28:07

微軟Windows 10卡頓

2025-07-28 04:00:00

Linux內存優化

2009-07-21 15:38:31

2019-04-28 11:08:13

Windows 10Windows操作系統

2021-01-18 05:19:11

數字指紋

2022-08-12 22:53:32

HadoopHDFS分布式
點贊
收藏

51CTO技術棧公眾號

日韩欧美视频| 午夜精品国产精品大乳美女| 久久久久无码精品国产sm果冻| 激情91久久| 精品免费久久久久久久| 日韩在线视屏| 女同毛片一区二区三区| 国产裸体歌舞团一区二区| 精品国产鲁一鲁一区二区三区| 亚洲情侣在线| 国产精品精品软件视频| 欧美日韩一区二区综合| 色一情一乱一乱一区91| 欧美色婷婷久久99精品红桃| 在线能看的av网站| 香蕉久久夜色精品国产| 日本黄色的视频| 在线日韩av片| 日韩精品视频在线观看一区二区三区| 久久亚洲一区二区三区四区| 国产人妻黑人一区二区三区| 色悠悠久久综合| 欧美熟妇另类久久久久久不卡 | 不卡福利视频| 欧美肥老妇视频| а√在线天堂官网| 色综合久久久久久久久五月| 国产精品视频在线观看免费| 亚洲成人av资源| 五月天av在线播放| 日本麻豆一区二区三区视频| 亚洲 自拍 另类 欧美 丝袜| 97精品国产99久久久久久免费| 国产在线一区二| 国产剧情一区二区| 一级久久久久久| www.午夜精品| 97超碰在线免费| 亚洲aaa激情| 亚洲午夜精品一区二区国产 | 18免费在线视频| 在线观看日韩专区| 欧美高清你懂的| av网站手机在线观看| 国产视频一区不卡| 国产亚洲小视频| 在线亚洲免费视频| 成人黄色网址| 中文字幕黄色大片| 久久夜色精品国产噜噜av| 国产在线视频网址| 91在线观看免费| 看电视剧不卡顿的网站| 无码人妻久久一区二区三区蜜桃 | 91九色蝌蚪91por成人| 亚洲视频在线免费观看| 蜜桃视频成人m3u8| 精品国产乱码久久久久久郑州公司| 清纯唯美亚洲经典中文字幕| 国产三级三级三级看三级| 欧美性猛交xxxx乱大交3| 亚洲黄色免费看| 亚洲国产精品久久久久婷婷老年| 激情六月婷婷久久| 亚洲精品天堂网| 91精品国产综合久久精品app| 东京一区二区| 亚洲av成人片色在线观看高潮| 欧美一区二区在线视频| 精品999成人| 日本免费网站视频| 欧美一级二级三级蜜桃| 免费观看一级欧美片| 男人的天堂成人| 国产一区二区三区成人欧美日韩在线观看 | 精品人妻一区二区三区蜜桃 | 日韩一级片在线观看| 网曝91综合精品门事件在线| 久久一区二区电影| 亚洲精品欧美日韩| 久久久高清一区二区三区| 日产精品久久久久久久性色| 日韩国产精品毛片| 欧美亚洲日本一区| 国产一区二区在线| 国产又黄又爽又色| 成人夜晚看av| 成人动漫在线一区| 可以在线观看的av网站| 一区二区三区视频在线播放| 国产精品无码永久免费888| 欧美一卡二卡| 午夜精品亚洲一区二区三区嫩草| 欧美三级免费观看| 日韩高清影视在线观看| 人妻少妇一区二区三区| 精品这里只有精品| 亚洲精品乱码久久久久久黑人| 2024最新电影在线免费观看| 免费精品99久久国产综合精品应用| 97国产在线观看| av激情亚洲男人天堂| 动漫一区在线| 女同久久另类69精品国产| 水蜜桃亚洲精品| 色婷婷国产精品| 欧美aaaaa性bbbbb小妇| 人妻 丝袜美腿 中文字幕| 欧美情侣性视频| 国产aⅴ综合色| 三级在线免费看| 日韩欧美久久一区| 欧美韩日精品| 国产成人免费观看视频 | 欧美啪啪小视频| 欧美亚洲在线播放| 不卡视频免费播放| 6080成人| 色哟哟一一国产精品| 国产91精品最新在线播放| 精品一区二区三区蜜桃| 亚洲女人18毛片水真多| 自拍偷拍亚洲色图欧美| 亚洲成人网在线观看| 国产一区二区三区四区五区美女 | 国产精品视频区| 亚洲二区免费| 中文字幕欧美在线观看| 国产精品免费视频一区二区| 91国产福利在线| eeuss影院一区二区三区| 成人av综合网| 久草手机在线视频| 人人妻人人澡人人爽欧美一区双| 国产精品第8页| 欧美在线免费观看亚洲| 美女诱惑一区二区| 成人福利av| 亚洲中文一区二区三区| 久久av综合网| 97精品一区二区三区| 美女一区二区久久| 91精品论坛| 九九热在线视频播放| 一区二区在线免费看| 欧美亚洲成人网| 亚洲精品一区中文| 成人精品电影在线观看| 极品少妇一区二区三区| 精品3atv在线视频| 伊人色综合久久久| 国产性生活毛片| 日韩欧美一区三区| av资源一区二区| 亚洲国产精品一区二区www| 五月综合久久| 玖玖综合伊人| 这里只有精品免费视频| 久久久亚洲精品无码| 亚洲国产精品小视频| 久久一区国产| 国产鲁鲁视频在线观看特色| 黄色片在线免费| 欧美精品一区在线| 欧洲精品视频在线观看| 极品销魂美女一区二区三区| 好看不卡的中文字幕| 国产乱人伦精品一区| 一区二区视频免费观看| 亚洲视频免费播放| 久久精品视频在线观看免费| 超碰97免费观看| 国产精品久久二区| 青草成人免费视频| 欧美日韩在线直播| 激情图区综合网| 国产精品一线| 97人人爽人人澡人人精品| 久草手机在线观看| 国产精品久久久久久9999| 久久99精品久久久久久水蜜桃| 欧美香蕉大胸在线视频观看| 久久精品国产久精国产爱| 999精品在线| 啊啊啊久久久| 精品人妻午夜一区二区三区四区| 国产乱人乱偷精品视频| 国内精品免费视频| 怡红院亚洲色图| 免费一级特黄毛片| 午夜精品美女自拍福到在线| 亚洲欧洲激情在线| 亚洲女在线观看| 午夜av一区二区三区| 日韩精品电影在线观看| 亚洲精华一区二区三区| 免费a级人成a大片在线观看| 人妻久久一区二区| 欧美成人精品欧美一级乱| 国产精品中文字幕久久久| 亚洲视频专区在线| 欧美日韩日日夜夜| 91老司机福利 在线| 欧美亚洲一区| 亚洲精品一区二区在线看| 美女免费久久| 日本成人一区二区三区| 天天综合网天天综合| 国产免费看av| 17c国产在线| 免费av观看网址| av免费观看国产| 国产 porn| 正在播放一区二区三区| 热re99久久精品国产99热| 91chinesevideo永久地址| 欧美高清dvd| 一区二区三区中文字幕| 亚洲一区二区av电影| av电影在线观看一区| 成人永久aaa| 美女网站色91| 国产欧美日韩精品一区| 日韩成人午夜电影| 久久久噜噜噜久久狠狠50岁| 91精品一区二区三区综合在线爱| 欧美一区二区三区免费看| 一本一道久久a久久精品蜜桃| 亚洲啊v在线观看| 99精品国产福利在线观看免费| 亚洲另类av| 色999日韩| 在线一区免费| 久久99国产精品免费网站| 99国内精品久久| 国精品**一区二区三区在线蜜桃| 91亚洲资源网| 91美女福利视频| 一本高清dvd不卡在线观看| 欧美人与z0zoxxxx视频| 综合欧美国产视频二区| 精品国产亚洲在线| 在线区一区二视频| 色综合久久99| 精品区一区二区| 亚洲尤物视频在线| 久久久久久久久久美女| 欧美激情一区二区三区不卡| 色av一区二区| 亚洲男人天堂2024| 日韩在线观看网站| 日韩精品视频在线免费观看| 亚洲精品自在久久| 欧美亚洲视频在线观看| 91在线无精精品一区二区| 欧美成ee人免费视频| 九9re精品视频在线观看re6| 久久久久久久中文| 国产精品333| 一本之道在线视频| 日韩肉感妇bbwbbwbbw| 黄色片网址在线观看| 欧美人与禽zoz0善交| 亚洲av无码一区二区三区网址| 欧美a级片免费看| 内射无码专区久久亚洲| 成人av观看| 欧美超碰在线| 老司机精品久久| 亚洲精品视频在线观看免费| 国产欧美精品在线观看| 亚洲国产视频一区二区| 亚洲美女视频网| 国产欧美日韩精品丝袜高跟鞋| 肉大捧一出免费观看网站在线播放 | 欧美亚洲第一页| 不卡中文字幕在线| 中国xxxx性xxxx产国| 欧美日韩理论片| 小泽玛利亚一区| 精品三级久久久久久久电影聊斋| 中文在线免费二区三区| 欧美一区二区三区久久精品茉莉花| 成人午夜在线免费| 亚洲成人第一页| 亚洲欧美国产一区二区三区| 成人黄色在线播放| 丰满人妻中伦妇伦精品app| 成人网站免费观看入口| 在线看片中文字幕| 五月婷婷六月丁香| av中文在线| 一区一区三区| 久久亚洲在线| 97久久精品人人爽人人爽蜜臀| 婷婷开心激情综合| 欧美日韩一区二区三区免费看| 国产精品a久久久久久| 久草精品电影| 天天影视色综合| 97精品人妻一区二区三区| 国产精品久久久久久吹潮| 久久久精品五月天| 亚洲综合区在线| 91精品国产电影| 日本xxxxxxx免费视频| 日本三级一区二区三区| 国产亚洲欧美日韩精品一区二区三区 | 神马精品久久| 欧美草逼视频| 亚洲综合色站| 偷拍一区二区三区四区| 欧美中文在线观看| а 天堂 在线| 日韩偷拍自拍| 伊人精品一区| 91蜜桃在线观看| 亚洲欧洲av一区二区| 欧美精品国产精品久久久| 国产精品情侣呻吟对白视频| heyzo高清中文字幕在线| 美国毛片一区二区| 日韩av一区在线| 日韩理论片在线观看| 免费高清一区二区三区| 欧产日产国产69| 黄色漫画在线免费看| 美女视频黄久久| 亚洲一区二区精品| 热久久这里只有精品| 黄色成人在线免费观看| 久久免费激情视频| 精品九九久久| 亚洲国产成人自拍| 欧美在线影院在线视频| 男人操女人下面视频| 午夜视频福利在线观看| 日韩精品永久网址| 欧美日韩你懂得| 97人人模人人爽视频一区二区| 国产一区二区三区无遮挡| 人妻无码一区二区三区| 牛牛影视精品影视| 在线免费高清一区二区三区| 午夜亚洲国产au精品一区二区| 91亚洲精品一区二区| 极品久久久久久久| 一区在线影院| 欧美亚洲在线| 一区二区成人精品| 亚洲综合av在线播放| 9191在线播放| 成人精品国产免费网站| 欧美一区二区三区人| 99免费在线观看视频| 国产又大又黑又粗免费视频| 欧美日韩播放| 成人免费高清在线| 97激碰免费视频| free性中国hd国语露脸| 日日夜夜天天综合入口| 欧美1区3d| 在线观看日韩av| 三上悠亚在线一区二区| 1区2区在线观看| 久久久国产精品不卡| 成人有码在线播放| 久久国产乱子伦精品| 亚洲v.com| 亚洲不卡一区二区三区| 在线成人av电影| 亚洲第一页综合| 2022成人影院| 91视频免费播放| 91视频免费在线观看| 在线观看中文字幕视频| 久久亚洲精精品中文字幕| 成人免费毛片app| 91精品久久久久久久久久久久久久| 国产xxxxhd| 成人精品毛片| 日韩精品视频免费| av网站有哪些| 美国十次av导航亚洲入口| 久久久精品免费网站| 97视频中文字幕| 国产一区二区三区四区视频| 久久亚洲精品伦理| 国产v综合ⅴ日韩v欧美大片| 中文字幕手机在线观看| 久草在线资源站手机版| 亚洲成人第一页| 北条麻妃在线一区| 日韩电影精品| 中文一区二区完整视频在线观看| 国产日韩欧美精品| 裸体xxxx视频在线| 久久婷婷久久一区二区三区| 久久久久国产精品视频| 色呦呦中文字幕|