当前位置: 首页 > article >正文

大文件分块上传和续传

给出一个Spring Boot项目中完成大文件分块上传和续传功能的完整示例代码解释,下面的示例将集中展示前端与后端的交互过程,将分别从客户端(前端)以及服务器端(后端)实现的角度来看实现思路。

定前端使用了axios进行与后端的交互,后端则利用Spring Boot来响应前端的请求和处理文件。

客户端(前端)实现

客户端的实现主要是利用axios或任何HTTP库,如fetch,来分块上传文件。在中断或失败后,能够获取已上传的信息并从断点处续传。

const axios = require('axios');
const FormData = require('form-data');

let currentOffset = 0;

const uploadFile = async (file, url) => {
    const chunkSize = 100 * 1024 * 1024; // 设定每块为100MB
    const totalSize = file.size;
    let formData = null;
  
    for (let offset = currentOffset; offset < totalSize; offset += chunkSize) {
        let end = Math.min(totalSize, offset + chunkSize);
        formData = new FormData();
        formData.append('file', file.slice(offset, end));
        formData.append('offset', offset.toString());

        try {
            const response = await axios.post(url, formData, {
                headers: {
                    'Content-Type': `multipart/form-data; boundary=${formData._boundary}`,
                },
            });
            if (response.data && response.data.status === 'ok') {
                currentOffset = end;
            }
        } catch (error) {
            console.error(`上传失败, 尝试重新上传片段: offset=${offset}`);
            await new Promise(resolve => setTimeout(resolve, 3000)); // 简易重试机制
        }
    }
};

// 使用
uploadFile(myFile, 'http://localhost:8080/uploadChunk');

在上述前端代码中,以固定大小(例如100MB)的chunk size分割文件,每个块由axios发送到后端服务器。同时会从断点处继续上传前块未传完的部分。

服务器端(后端)实现

在服务器端(后端)实现要确保正确拼接接收到的文件块,使用AtomicLong或其他数据库来持久化偏移量情况,便于跟踪文件的上传状态。

import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.http.HttpStatus;

import java.io.IOException;
import java.nio.file.Paths;
import java.util.concurrent.atomic.AtomicLong;

@RestController
public class FileUploadController {

    AtomicLong currentOffset = new AtomicLong(0);
    private final static String UPLOAD_FOLDER = Paths.get(System.getProperty("user.home"), "uploads").toString();
    private final static long CHUNK_SIZE = 100 * 1024 * 1024; // 与前端chunk size相同

    @PostMapping("/uploadChunk")
    public ResponseEntity<String> handleFileUpload(@RequestParam("file") MultipartFile file,
                                                   @RequestParam("offset") long offset) throws IOException {
        long end = Math.min(offset + file.getSize(), file.getSize());
        
        if (currentOffset.get() < offset) {
            currentOffset.set(offset);
        }

        Path filePath = Paths.get(UPLOAD_FOLDER, "uploadedFile");
        
        Files.createDirectories(filePath.getParent());
        Files.write(filePath, file.getBytes(), StandardOpenOption.APPEND);
        
        currentOffset.set(end);
        return ResponseEntity.status(HttpStatus.OK).body("{\"status\": \"ok\"}");
    }
}

在后端代码段中,接收分块并拼接文件,同时通过AtomicLong或其他方法储存断点上传的状态。

总结

从嵌入上述示例代码中,控制与处理大文件的断点续传与分块上传,关键技能遵照如下:

  1. 连续和可恢复的上传方案 – 前端处理正确分块的文件,后端则保证按文件块合并存储。
  2. 状态追踪 – 最佳实践是将状态信息持久化,以便在长时间运行或服务重启之后可以重新获取信息。
  3. 健壮的错误处理 – 在可能的失败场景下提供适当的异常处理与重试机制。
  4. 前后端一致 – 持有相同的chunk大小,可以避免编码中对于边界处理的复杂逻辑,从而减少出错的几率。

增进完善与优化策略

上述方案的直观,初步简推出了大文件的分块上传与断点续传结构。然而,通常在生产系统中,会添加更多高级特性以优化性能和可靠性。比如使用数据库存储上传状态(而非在内存中存储),采用更复杂的错误恢复策略,建立互操作协议报告上传进度,引入健康检查机制确认网络或系统状态,利用分布式系统(如云存储)优势中实现数据冗余等。


http://www.kler.cn/a/287827.html

相关文章:

  • Zotero 7本地pdf文件名自适应中英文格式
  • MySQL数据库:SQL语言入门 【3】(学习笔记)
  • 第二十一周机器学习笔记:动手深度学习之——数据操作、数据预处理
  • ubuntu22 安装 minikube
  • 车载诊断架构 --- 关于DTC的开始检测条件
  • 如何在 Ubuntu 上安装 Jellyfin 媒体服务器
  • LLC电路全桥和半桥工作原理详解
  • 《深入浅出WPF》读书笔记.10资源
  • 鸿蒙开发 ImageKnife二次封装
  • 数据结构(邓俊辉)学习笔记】串 07——KMP算法:分摊分析
  • 【python因果推断库2】使用 PyMC 模型进行差分-in-差分(Difference in Differences, DID)分析
  • 【rk3588】环境搭建及系统编译
  • css实现元素居中显示
  • 【Qt窗口】—— 浮动窗口
  • jarbas 靶机渗透(cms 渗透)
  • 2700+存储过程的超复杂Oracle,国产化怎么办?
  • unreal engine5.4.3动画重定向
  • android so的加载流程(Android 13~14)
  • js代码如何和服务端进行通信
  • 开发软件国内镜像下载总结
  • Docker 安装消息队列RabbitMQ
  • OpenHarmony技术开发:Launcher架构应用启动流程分析
  • Cyberchef实用功能之-json解析美化和转换
  • Java 面试题:HTTP缓存:强制缓存和协商缓存--xunznux
  • threejs中OrbitControls的用法
  • docker实战扩展三(dockerfile中run的详细用法)