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

Django模型FileField上传1GB大文件报错 分块上传及其他解决方案咨询

Django 1GB大文件上传报错解决方案

你遇到的RequestDataTooBig报错本质是Django默认DATA_UPLOAD_MAX_MEMORY_SIZE参数限制了单次请求体最大为2.5MB,整包上传1GB文件直接超过阈值触发拦截。以下是三类可行解决方案:

1. 临时快速解决方案(低并发、内部使用场景)

不需要修改上传逻辑,调整配置即可直接使用,适合仅在admin后台上传、使用频率低的场景:

  • 在项目settings.py中调整两个核心参数:
# 调整单次请求最大允许大小,此处设置为2GB,可按需调整
DATA_UPLOAD_MAX_MEMORY_SIZE = 2 * 1024 * 1024 * 1024
# 调整文件内存缓存阈值,超过该值的文件自动写入临时磁盘,避免占满服务器内存
FILE_UPLOAD_MAX_MEMORY_SIZE = 10 * 1024 * 1024  # 设为10MB
  • 若使用Nginx等反向代理,需要同步调整代理层的请求大小限制,否则会被反向代理提前拦截,Nginx配置示例:
server {
    # 其他配置保持不变
    client_max_body_size 2G;
}

该方案缺点是不支持断点续传,上传过程中网络中断需要重新上传整个文件,大文件上传失败概率高,不适合面向普通用户的公共上传入口。

2. 分块上传实现方案(自研生产场景)

分块上传逻辑是前端将大文件切割为固定大小的小块(一般每块5~20MB),逐块上传到后端,后端全部接收完成后合并为完整文件关联到模型,支持断点续传、上传进度展示,适合高频大文件上传场景:

后端实现

首先新增分块上传临时记录表,存储上传的块信息:

from django.db import models
import os
from django.conf import settings

class ChunkUpload(models.Model):
    file_md5 = models.CharField(max_length=32, verbose_name="文件唯一MD5", db_index=True)
    chunk_index = models.IntegerField(verbose_name="块序号")
    total_chunks = models.IntegerField(verbose_name="总块数")
    chunk_file = models.FileField(upload_to="chunk_temp/", verbose_name="临时块文件")
    filename = models.CharField(max_length=255, verbose_name="原始文件名")

    class Meta:
        unique_together = ('file_md5', 'chunk_index')

新增三个接口完成全流程:

  • 秒传校验接口:前端上传前传递文件MD5和文件名,后端先校验是否已经存在上传完成的相同文件,存在直接返回文件地址无需重复上传
  • 块上传接口:接收前端传递的块数据、MD5、块序号、总块数,存储到ChunkUpload表
  • 合并接口:前端全部块上传完成后调用,按序号合并所有块为完整文件,存储到你原有save_support_file指定的路径,关联到Software模型的software_file字段后删除临时块数据
    合并核心逻辑示例:
def merge_file_chunks(file_md5, total_chunks, filename):
    chunks = ChunkUpload.objects.filter(file_md5=file_md5).order_by('chunk_index')
    if chunks.count() != total_chunks:
        raise ValueError("上传块缺失,合并失败")
    # 调用原有路径生成逻辑获取保存路径
    save_relative_path = save_support_file(Software(), filename)
    full_save_path = os.path.join(settings.MEDIA_ROOT, save_relative_path)
    # 合并文件
    with open(full_save_path, 'wb') as full_file:
        for chunk in chunks:
            with open(chunk.chunk_file.path, 'rb') as chunk_f:
                full_file.write(chunk_f.read())
            # 清理临时块
            chunk.chunk_file.delete()
            chunk.delete()
    return save_relative_path

前端实现

前端借助SparkMD5计算文件唯一MD5,按固定大小切割文件逐块上传,示例逻辑:

const CHUNK_SIZE = 10 * 1024 * 1024 // 每块10MB
const uploadFile = document.getElementById('file-input').files[0]
const totalChunks = Math.ceil(uploadFile.size / CHUNK_SIZE)
// 此处省略SparkMD5计算文件MD5的逻辑
// 逐块上传
for (let i = 0; i < totalChunks; i++) {
    const chunk = uploadFile.slice(i * CHUNK_SIZE, (i + 1) * CHUNK_SIZE)
    const formData = new FormData()
    formData.append('chunk', chunk)
    formData.append('chunk_index', i)
    formData.append('total_chunks', totalChunks)
    formData.append('file_md5', 文件MD5值)
    formData.append('filename', uploadFile.name)
    // 调用块上传接口,可控制并发数避免请求过多
}
// 全部上传完成后调用合并接口,获取完整文件路径后提交Software模型的其他字段(分类、关联产品等)

3. 对象存储直传方案(低维护生产场景)

该方案不需要自研分块上传逻辑,稳定性更高,适合生产环境高并发场景:

  • 申请阿里云OSS、腾讯云COS等对象存储服务,所有服务商都已封装好大文件分块上传、断点续传能力
  • 前端直接调用对象存储的JS SDK将文件上传到存储服务,上传完成后获取文件的公网访问地址
  • 后端仅需要将该地址存储到Software模型的software_file字段即可,不需要处理文件上传逻辑,也不会有请求大小限制问题
    该方案优势是不需要占用服务器带宽和存储资源,维护成本极低,上传稳定性远高于自研分块上传。

内容的提问来源于stack exchange,提问作者Hüseyin Daş

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 08:39:03