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

InMemoryUploadedFile转Google MediaUpload触发UnicodeDecodeError

问题根因
  • Google App Engine标准环境实例的文件系统为只读模式,Django接收体积小于默认阈值的上传文件时,会自动生成内存存储的InMemoryUploadedFile实例,不会写入本地磁盘,该行为符合环境特性。
  • 你使用的MediaFileUpload类仅支持传入本地文件路径入参,会自行从磁盘读取文件内容,不支持直接传入内存文件实例或者bytes对象。你把读取到的字节内容当文件路径传入后,类内部会尝试将字节作为路径字符串解析,最终触发类型错误、UnicodeDecodeError。
修复方案

替换上传类为专门适配内存流的MediaIoBaseUpload,全程不需要写入本地磁盘,完全适配GAE只读环境:

  1. 补充导入所需依赖
import io
from googleapiclient.http import MediaIoBaseUpload
  1. 修正上传逻辑,替换原有MediaFileUpload相关代码即可,完整参考实现:
def expupdate(request):
    try:
        creds, _ = google.auth.default()
        service = build('drive', 'v3', credentials=creds)
        myfile = request.FILES['archivo']
        Mtype = myfile.content_type
        
        # 小文件方案:读字节包装为内存流
        file_stream = io.BytesIO(myfile.read())
        media = MediaIoBaseUpload(
            file_stream,
            mimetype=Mtype,
            resumable=False
        )

        # 大文件优化方案:不需要全量读入内存,直接传InMemoryUploadedFile实例即可
        # 该类本身实现了标准类文件read接口,内存占用更低
        # media = MediaIoBaseUpload(myfile, mimetype=Mtype, resumable=True)

        file_metadata = {'name': 'test.jpeg'}
        file = service.files().create(
            body=file_metadata,
            media_body=media,
            fields='id'
        ).execute()
        fileid = file.get("id")
        print(fileid)
        file_stream.close()

    except Exception as e:
        print('An error occurred:')
        print(e)
避坑提示
  • 不要对上传文件的二进制内容做任何字符串解码操作,图片、办公文档等二进制文件做字符串解码必然触发UnicodeDecodeError。
  • 上传体积超过10M的文件建议将resumable参数设为True,开启分片续传,避免大文件上传超时。
  • 不需要额外把InMemoryUploadedFile转成bytes再包装,直接传入MediaIoBaseUpload就能正常工作,可减少一次内存拷贝。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 03:09:16