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

基于Django与django-storages向GCS传大文件:直传或分片方案?

解决方案:Google App Engine上Django大文件上传至GCS的问题

问题1:能否通过django-storages发起多个POST请求分批上传?

直接用django-storages默认逻辑做不到自动分批上传——它是在Django处理表单提交时,一次性把所有文件传到App Engine再转发到GCS,这直接触发了GAE的32MB POST限制。
要实现分批上传,得自己修改逻辑:先保存模型的非文件字段(或暂存),再单独对每个文件字段发起异步请求,逐个上传到GCS,最后把GCS文件路径关联到模型。但这种方式需要自定义视图和表单,django-storages本身不提供分批上传功能。

问题2:如何实现Django直传文件至GCS?

这是更推荐的方案,绕开App Engine的POST限制,直接从客户端传文件到GCS:

  1. 后端生成签名URL
    写一个接口生成GCS的签名上传URL,指定允许的文件类型、大小、过期时间等参数,用google-cloud-storage库实现:
    from google.cloud import storage
    from django.conf import settings
    from django.http import JsonResponse
    import uuid
    from datetime import datetime, timedelta
    
    def get_upload_url(request):
        bucket_name = settings.GS_BUCKET_NAME
        storage_client = storage.Client()
        bucket = storage_client.bucket(bucket_name)
        blob_name = f"uploads/{request.user.id}/{uuid.uuid4()}"
        blob = bucket.blob(blob_name)
        
        # 生成有效期1小时的PUT请求签名URL
        url = blob.generate_signed_url(
            version="v4",
            expiration=timedelta(hours=1),
            method="PUT",
            content_type="image/jpeg"  # 根据实际文件类型调整
        )
        return JsonResponse({"upload_url": url, "blob_name": blob_name})
    
  2. 前端直传文件
    在后台管理页面用JS监听文件选择事件,调用上述接口获取签名URL,通过PUT请求直接把文件传到GCS。上传完成后,把返回的blob_name(GCS中的文件路径)填入表单对应字段,而非上传文件本身。
  3. 模型字段适配
    模型中可以用CharField存储GCS路径,也可以保留FileField并配置django-storages的GSFileStorage,让它直接读取GCS路径,无需额外上传操作。

问题3:如何修改Django后台管理界面的上传逻辑?

需要自定义Admin的表单和模板:

  1. 自定义Admin表单
    把原文件字段改成隐藏的CharField(用于存储GCS路径),用自定义组件替代默认上传框:
    from django.contrib import admin
    from django import forms
    from .models import MediaModel
    
    class MediaModelForm(forms.ModelForm):
        image1 = forms.CharField(widget=forms.HiddenInput(), required=False)
        image2 = forms.CharField(widget=forms.HiddenInput(), required=False)
    
        class Meta:
            model = MediaModel
            fields = "__all__"
    
    class MediaModelAdmin(admin.ModelAdmin):
        form = MediaModelForm
        change_form_template = "admin/media_model_change_form.html"
    
  2. 自定义Admin模板
    在admin/media_model_change_form.html中添加自定义上传按钮和JS逻辑,实现直传流程:
    document.getElementById('image-upload-btn').addEventListener('click', async () => {
        const file = document.getElementById('image-file-input').files[0];
        if (!file) return;
        
        // 获取签名URL
        const resp = await fetch('/admin/get-upload-url/', { method: 'GET' });
        const data = await resp.json();
        
        // 直传文件到GCS
        await fetch(data.upload_url, {
            method: 'PUT',
            body: file,
            headers: { 'Content-Type': file.type }
        });
        
        // 把GCS路径填入隐藏字段
        document.getElementById('id_image1').value = data.blob_name;
        alert('上传完成');
    });
    
  3. 完善保存逻辑
    在Admin的save_model方法中,确保保存的是GCS路径而非本地文件。如果用FileField,django-storages会自动根据路径读取GCS文件,无需额外处理。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 12:45:08