成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

SpringBoot大文件上傳卡死?分塊切割術搞定GB級傳輸,速度飆升!!!

開發 前端
分塊上傳就像把大文件運輸變成一場接力賽,每個分片都是一個選手,各司其職,共同完成任務。通過分塊切割、斷點續傳、并行加速和安全防護,我們不僅解決了大文件上傳的卡死問題,還提升了用戶體驗和系統性能。現在,你可以自信地對用戶說:不管多大的文件,我們都能輕松搞定!

兄弟們,當你正在開發一個視頻網站,用戶要上傳一個 5GB 的 4K 視頻。傳統的 SpringBoot 單文件上傳就像開著一輛裝滿貨物的三輪車爬坡 ——內存爆炸、超時崩潰、網絡波動分分鐘讓你前功盡棄。這時候,分塊切割術就像給三輪車裝上渦輪增壓,把大文件切成小塊分批運輸,讓上傳過程變得像高鐵一樣平穩高效。

一、傳統上傳的「死亡陷阱」

1. 內存黑洞

SpringBoot 默認用MultipartFile接收文件,大文件會直接加載到內存。5GB 的文件相當于把一頭大象塞進小轎車,內存直接溢出,服務器瞬間卡死。

2. 超時魔咒

HTTP 請求有默認超時時間(Tomcat 默認 60 秒),上傳一個 5GB 文件需要至少 10 分鐘,超時是必然的。用戶只能眼睜睜看著進度條卡在 99%,然后重新再來。

3. 網絡過山車

上傳到一半突然斷網,傳統方案只能從頭再來。用戶可能已經等了半小時,結果竹籃打水一場空,這種體驗簡直讓人想砸電腦。

二、分塊切割術的「九陽神功」

1. 分而治之的智慧

把大文件切成 20MB 的小塊,就像把大象拆成零件運輸。每個小塊獨立上傳,失敗了只需要重傳那一塊,大大降低風險。

2. 斷點續傳的魔法

記錄已經上傳的分片,網絡恢復后從斷點繼續。用戶可以暫停、重啟上傳,甚至關閉電腦第二天接著傳,就像下載電影一樣方便。

3. 并行加速的奧義

同時上傳多個分片,充分利用帶寬。就像多條車道同時通車,上傳速度直接翻倍。

三、后端實現:打造「文件運輸線」

1. 數據庫設計:記錄運輸狀態

CREATE TABLE file_upload (
    id VARCHAR(36) PRIMARY KEY, -- 文件唯一標識
    total_size BIGINT NOT NULL, -- 文件總大小
    total_chunks INT NOT NULL, -- 總分片數
    uploaded_chunks INT DEFAULT 0, -- 已上傳分片數
    status INT DEFAULT 0 -- 0-進行中,1-完成,2-失敗
);

2. 分片上傳接口:接收零件

@PostMapping("/upload/chunk")
public ResponseEntity<?> uploadChunk(
    @RequestParam("file") MultipartFile chunk,
    @RequestParam("fileId") String fileId,
    @RequestParam("chunkIndex") int chunkIndex) {
    
    // 檢查分片是否已存在
    if (chunkRepository.existsByFileIdAndChunkIndex(fileId, chunkIndex)) {
        return ResponseEntity.ok("分片已存在");
    }
    
    // 保存分片到臨時目錄
    String chunkPath = Paths.get(uploadDir, fileId, chunkIndex + ".part").toString();
    chunk.transferTo(Paths.get(chunkPath));
    
    // 更新數據庫狀態
    chunkRepository.save(new Chunk(fileId, chunkIndex, chunk.getSize()));
    
    return ResponseEntity.ok("分片上傳成功");
}

3. 合并接口:組裝零件

@PostMapping("/upload/merge")
public ResponseEntity<?> mergeChunks(@RequestParam("fileId") String fileId) {
    // 查詢所有分片
    List<Chunk> chunks = chunkRepository.findByFileId(fileId);
    
    // 按順序合并
    try (RandomAccessFile target = new RandomAccessFile(Paths.get(uploadDir, fileId).toFile(), "rw")) {
        for (Chunk chunk : chunks) {
            try (FileInputStream in = new FileInputStream(Paths.get(uploadDir, fileId, chunk.getChunkIndex() + ".part").toFile())) {
                byte[] buffer = new byte[1024];
                int bytesRead;
                while ((bytesRead = in.read(buffer)) != -1) {
                    target.write(buffer, 0, bytesRead);
                }
            }
        }
    }
    
    // 刪除臨時分片
    chunks.forEach(chunk -> {
        try {
            Files.delete(Paths.get(uploadDir, fileId, chunk.getChunkIndex() + ".part"));
        } catch (IOException e) {
            log.error("刪除分片失敗", e);
        }
    });
    
    // 更新文件狀態
    fileUploadRepository.updateStatus(fileId, 1);
    
    return ResponseEntity.ok("文件合并成功");
}

四、前端實現:「零件加工廠」

1. 分片切割:拆大象

function splitFile(file, chunkSize = 20 * 1024 * 1024) {
    const chunks = [];
    let current = 0;
    while (current < file.size) {
        const chunk = file.slice(current, current + chunkSize);
        chunks.push(chunk);
        current += chunkSize;
    }
    return chunks;
}

2. 并行上傳:多條車道

async function uploadChunks(chunks, fileId) {
    const promises = chunks.map((chunk, index) => {
        const formData = new FormData();
        formData.append("file", chunk);
        formData.append("fileId", fileId);
        formData.append("chunkIndex", index);
        
        return fetch("/upload/chunk", {
            method: "POST",
            body: formData
        });
    });
    
    await Promise.all(promises);
}

3. 進度條:實時反饋

<div class="progress">
    <div class="progress-bar" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100"></div>
</div>
<script>
function updateProgress(uploaded, total) {
    const progressBar = document.querySelector('.progress-bar');
    progressBar.style.width = `${(uploaded / total) * 100}%`;
    progressBar.setAttribute('aria-valuenow', `${(uploaded / total) * 100}`);
}
</script>

五、斷點續傳:「失敗重來」的勇氣

1. 記錄上傳狀態

localStorage.setItem('uploadStatus', JSON.stringify({
    fileId: '123',
    uploadedChunks: [0, 1, 3]
}));

2. 恢復上傳

async function resumeUpload(file) {
    const status = JSON.parse(localStorage.getItem('uploadStatus'));
    const chunks = splitFile(file);
    
    // 找出未上傳的分片
    const remainingChunks = chunks.filter((_, index) => !status.uploadedChunks.includes(index));
    
    await uploadChunks(remainingChunks, status.fileId);
}

六、性能優化:「速度與激情」

1. 異步處理:解放線程

@Async("fileUploadExecutor")
public CompletableFuture<?> asyncMerge(String fileId) {
    return CompletableFuture.runAsync(() -> {
        // 合并文件邏輯
    });
}

2. 動態分塊:適應路況

function calculateChunkSize(bandwidth) {
    // 根據網絡帶寬動態調整分片大小
    return Math.max(10 * 1024 * 1024, Math.min(50 * 1024 * 1024, bandwidth * 0.8));
}

3. 多線程合并:同時組裝

ExecutorService executor = Executors.newFixedThreadPool(4);
List<Future<?>> futures = new ArrayList<>();

for (int i = 0; i < chunks.size(); i += 4) {
    final int start = i;
    futures.add(executor.submit(() -> {
        for (int j = start; j < Math.min(start + 4, chunks.size()); j++) {
            // 合并分片
        }
    }));
}

futures.forEach(future -> {
    try {
        future.get();
    } catch (Exception e) {
        log.error("合并失敗", e);
    }
});

七、安全防護:「文件運輸的保險」

1. MD5 校驗:防篡改

@PostMapping("/upload/check")
public ResponseEntity<?> checkFile(@RequestParam("file") MultipartFile file) {
    String md5 = calculateMD5(file.getInputStream());
    FileUpload fileUpload = fileUploadRepository.findByMd5(md5);
    
    if (fileUpload != null && fileUpload.getStatus() == 1) {
        return ResponseEntity.ok("文件已存在");
    }
    
    return ResponseEntity.ok("文件不存在");
}

2. 文件類型驗證:防病毒

@PostMapping("/upload/chunk")
public ResponseEntity<?> uploadChunk(@RequestParam("file") MultipartFile chunk) {
    String contentType = chunk.getContentType();
    if (!contentType.startsWith("image/") && !contentType.startsWith("video/")) {
        return ResponseEntity.badRequest().body("不支持的文件類型");
    }
    
    // 其他邏輯
}

3. 權限控制:防越權

@PreAuthorize("hasRole('ROLE_ADMIN')")
@PostMapping("/upload/merge")
public ResponseEntity<?> mergeChunks(@RequestParam("fileId") String fileId) {
    // 合并邏輯
}

八、實戰案例:「5GB 視頻上傳的逆襲」

1. 傳統方案

  • 上傳時間:15 分鐘
  • 內存占用:800MB
  • 失敗率:30%(網絡波動)

2. 分塊方案

  • 上傳時間:4 分鐘(并行上傳)
  • 內存占用:50MB(流式處理)
  • 失敗率:2%(斷點續傳)

九、總結:「分塊切割術」的終極奧義

分塊上傳就像把大文件運輸變成一場接力賽,每個分片都是一個選手,各司其職,共同完成任務。通過分塊切割、斷點續傳、并行加速和安全防護,我們不僅解決了大文件上傳的卡死問題,還提升了用戶體驗和系統性能。現在,你可以自信地對用戶說:不管多大的文件,我們都能輕松搞定!

責任編輯:武曉燕 來源: 石杉的架構筆記
相關推薦

2025-06-27 02:32:00

2025-04-10 08:03:31

Spring系統

2020-08-14 11:01:32

數據Pandas文件

2024-09-26 09:28:06

內存Spring

2021-11-26 22:01:26

Linux傳輸網絡

2021-06-07 00:03:31

HTTP大文件方案

2009-11-16 11:41:19

PHP上傳大文件

2022-06-13 14:06:33

大文件上傳前端

2025-05-06 01:21:00

C#內存SIMD

2022-08-16 16:00:05

Python

2010-09-07 16:11:55

CSS Sprites

2009-07-21 15:38:31

2021-01-15 11:40:44

文件Java秒傳

2011-12-14 09:57:17

最快網絡傳輸速度186GB

2021-06-10 09:05:43

Linux命令大文件切割

2014-03-10 17:17:53

西數My Passport試用

2022-08-12 22:53:32

HadoopHDFS分布式

2024-07-02 10:18:18

2013-05-29 09:59:20

Java-RMI遠程調用

2009-12-07 09:45:23

PHP上傳大文件設置
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 国产成人jvid在线播放 | 亚洲九色 | 先锋影音资源网站 | 亚洲成人国产综合 | 亚洲精品欧美一区二区三区 | 中文成人在线 | 亚洲高清一区二区三区 | av网站免费观看 | 成人在线一区二区 | 日本精a在线观看 | 久久久久9999| 在线视频 亚洲 | 影音先锋中文字幕在线观看 | 亚洲免费视频在线观看 | 色片在线观看 | 99久久99久久精品国产片果冰 | 一区二区在线不卡 | 精品视频www | 久久久久久久久久久久久久av | 国产一级一片免费播放 | 日本亚洲欧美 | 亚洲成人在线视频播放 | 亚洲欧美久久 | 天天射网站 | 亚洲精品在线视频 | 精品国产一区二区 | 一区二区三区回区在观看免费视频 | 日本精品国产 | 久久人人爽人人爽 | 91性高湖久久久久久久久_久久99 | 日日干夜夜操 | www.国产一区 | 国产精品成人一区二区三区夜夜夜 | 日本 欧美 国产 | 一级片在线观看 | 九九久久这里只有精品 | av手机免费在线观看 | 成人一区二区三区在线观看 | 麻豆久久久 | 日韩欧美精品 | 午夜电影福利 |