You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

异步分片上传.tar文件至Flask后端失败,解压报错求助

问题排查与解决思路

核心原因

异步上传时,浏览器会并行发送分片请求,后端接收分片的顺序不一定和前端发送的顺序一致,直接按接收顺序拼接文件会导致tar文件结构错乱,解压时触发头部识别错误。

后端修复方案(api.py)

需要修改后端逻辑,让每个分片携带分片索引和总分片数,后端先存储所有分片,等全部接收完成后再按正确顺序拼接。

修改后的api.py示例

from flask import Flask, request, jsonify
import os
from uuid import uuid4

app = Flask(__name__)
UPLOAD_FOLDER = './uploads'
os.makedirs(UPLOAD_FOLDER, exist_ok=True)

@app.route('/upload', methods=['POST'])
def upload_chunk():
    # 获取分片信息
    chunk_idx = int(request.form['chunkIndex'])
    total_chunks = int(request.form['totalChunks'])
    file_id = request.form['fileId']
    chunk = request.files['chunk']
    
    # 创建临时目录存储分片
    temp_dir = os.path.join(UPLOAD_FOLDER, file_id)
    os.makedirs(temp_dir, exist_ok=True)
    
    # 保存分片,文件名带索引保证顺序
    chunk_path = os.path.join(temp_dir, f'chunk_{chunk_idx}')
    chunk.save(chunk_path)
    
    # 检查是否所有分片都已上传
    uploaded_chunks = len([f for f in os.listdir(temp_dir) if f.startswith('chunk_')])
    if uploaded_chunks == total_chunks:
        # 按索引顺序拼接所有分片
        final_file_path = os.path.join(UPLOAD_FOLDER, f'{file_id}.tar')
        with open(final_file_path, 'wb') as final_file:
            for i in range(total_chunks):
                chunk_file_path = os.path.join(temp_dir, f'chunk_{i}')
                with open(chunk_file_path, 'rb') as cf:
                    final_file.write(cf.read())
                # 删除临时分片文件
                os.remove(chunk_file_path)
        # 删除临时目录
        os.rmdir(temp_dir)
        return jsonify({'status': 'success', 'message': 'File uploaded completely'})
    
    return jsonify({'status': 'pending', 'message': 'Chunk uploaded'})

if __name__ == '__main__':
    app.run(debug=True)

前端配合修改(upload.js)

需要给每个分片请求添加chunkIndex、totalChunks和唯一fileId,确保后端能识别分片顺序:

修改后的upload.js示例

function uploadFile(file) {
    const chunkSize = 1024 * 1024; // 1MB分片
    const totalChunks = Math.ceil(file.size / chunkSize);
    const fileId = self.crypto.randomUUID(); // 生成唯一文件ID

    for (let i = 0; i < totalChunks; i++) {
        const start = i * chunkSize;
        const end = Math.min(start + chunkSize, file.size);
        const chunk = file.slice(start, end);

        const formData = new FormData();
        formData.append('chunk', chunk);
        formData.append('chunkIndex', i);
        formData.append('totalChunks', totalChunks);
        formData.append('fileId', fileId);

        const xhr = new XMLHttpRequest();
        xhr.open('POST', '/upload', true); // 异步模式
        xhr.onload = function() {
            if (xhr.status === 200) {
                console.log(`Chunk ${i} uploaded`);
            }
        };
        xhr.send(formData);
    }
}

关键注意点

  • 必须通过唯一fileId关联同一个文件的所有分片,避免不同文件的分片混淆。
  • 后端拼接时严格按照chunkIndex从小到大的顺序写入,不能按接收顺序拼接。
  • 临时分片上传完成后要及时清理,避免占用磁盘空间。

内容的提问来源于stack exchange,提问作者Luca

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 13:57:18