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

基于JavaScript Ajax和Django的2GB大文件分块上传问题求助

Django + JavaScript Ajax 2GB大文件分块上传问题解决方案

问题1:views.py无法拼接完整文件解决方案

核心原因大多为块顺序混乱、文件标识冲突、合并逻辑错误,可按以下逻辑修改views.py代码:

import os
from django.conf import settings
from django.http import JsonResponse
from django.views.decorators.csrf import csrf_exempt

@csrf_exempt
def upload_chunk(request):
    if request.method == 'POST':
        # 前端必须传递的三个参数:文件唯一标识、当前块序号、总块数
        file_md5 = request.POST.get('file_md5')
        chunk_index = int(request.POST.get('chunk_index', 0))
        total_chunks = int(request.POST.get('total_chunks', 1))
        # 当前块二进制内容
        chunk_file = request.FILES.get('chunk')
        
        # 每个文件单独创建临时目录存储块,避免不同文件块冲突
        temp_chunk_dir = os.path.join(settings.MEDIA_ROOT, 'temp_chunks', file_md5)
        os.makedirs(temp_chunk_dir, exist_ok=True)
        
        # 存储当前块
        chunk_save_path = os.path.join(temp_chunk_dir, f'chunk_{chunk_index}')
        with open(chunk_save_path, 'wb+') as f:
            for seg in chunk_file.chunks():
                f.write(seg)
        
        # 校验所有块是否上传完成
        uploaded_chunk_count = len(os.listdir(temp_chunk_dir))
        if uploaded_chunk_count == total_chunks:
            # 拼接生成最终文件
            final_file_name = request.POST.get('file_name', f'{file_md5}.dat')
            final_file_path = os.path.join(settings.MEDIA_ROOT, 'completed_uploads', final_file_name)
            os.makedirs(os.path.dirname(final_file_path), exist_ok=True)
            
            with open(final_file_path, 'wb') as final_f:
                # 按数字序号顺序读取块,禁止直接按文件名排序,避免字符串排序导致顺序错误
                for i in range(total_chunks):
                    current_chunk_path = os.path.join(temp_chunk_dir, f'chunk_{i}')
                    with open(current_chunk_path, 'rb') as chunk_f:
                        final_f.write(chunk_f.read())
                    # 合并完成后删除已用块
                    os.remove(current_chunk_path)
            # 删除空的临时块目录
            os.rmdir(temp_chunk_dir)
            return JsonResponse({'code': 0, 'msg': '文件上传完成', 'save_path': final_file_path})
        
        return JsonResponse({'code': 0, 'msg': '当前块上传成功'})
    return JsonResponse({'code': 1, 'msg': '请求方法不支持'})

特别注意:Django settings.py中需要新增配置DATA_UPLOAD_MAX_MEMORY_SIZE = 15 * 1024 * 1024,值要大于单块大小,避免请求被Django默认拦截

问题2:视频上传耗时过长优化方案

  • 调整单块大小为5MB~10MB,平衡请求次数和单请求失败重传成本,2GB文件用10MB块仅需204次请求,综合效率最高
  • 前端开启3~5并发上传,不要串行传块,示例JS逻辑如下:
const CONCURRENT_LIMIT = 4; // 并发上传数,不建议超过5
const CHUNK_SIZE = 10 * 1024 * 1024; // 单块10MB

// 并发任务控制函数
async function runConcurrentTasks(tasks, limit) {
  const executing = [];
  for (const task of tasks) {
    const p = Promise.resolve().then(() => task());
    executing.push(p);
    if (executing.length >= limit) {
      await Promise.race(executing);
      executing.splice(executing.findIndex(e => e === p), 1);
    }
  }
  await Promise.all(executing);
}

// 单块上传函数
async function uploadSingleChunk(chunk, chunkIndex, totalChunks, fileMd5, fileName) {
  const formData = new FormData();
  formData.append('chunk', chunk);
  formData.append('chunk_index', chunkIndex);
  formData.append('total_chunks', totalChunks);
  formData.append('file_md5', fileMd5);
  formData.append('file_name', fileName);
  await fetch('/upload_chunk/', {
    method: 'POST',
    body: formData
  });
}

// 总上传入口
async function handleFileUpload(file) {
  // 可引入spark-md5计算文件唯一md5,避免文件重名冲突
  const fileMd5 = await calcFileMd5(file); 
  const totalChunks = Math.ceil(file.size / CHUNK_SIZE);
  const tasks = [];
  for (let i = 0; i < totalChunks; i++) {
    const start = i * CHUNK_SIZE;
    const end = Math.min(start + CHUNK_SIZE, file.size);
    const chunk = file.slice(start, end);
    tasks.push(() => uploadSingleChunk(chunk, i, totalChunks, fileMd5, file.name));
  }
  await runConcurrentTasks(tasks, CONCURRENT_LIMIT);
  alert('文件上传完成');
}
  • 新增断点续传逻辑:上传前前端先请求后端查询当前文件已上传的块列表,跳过已上传的块,断网重连不需要从头上传
  • Nginx部署的用户需在Nginx配置中新增client_max_body_size 15M;,避免块请求被Nginx拦截

内容的提问来源于stack exchange,提问作者Subhra Kanti Ray

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 19:54:08