异步分片上传.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
相关产品推荐
相关产品推荐

