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

使用Django REST Framework在GCP上传图片时遭遇UnicodeDecodeError错误求助

问题排查与解决方法

这个UnicodeDecodeError的核心原因是你错误地处理了上传的文件对象,把二进制图片当成UTF-8文本内容来解析,同时误用了GCS的上传方法。下面一步步给你拆解问题和解决思路:

问题根源分析

  1. 错误的文件对象处理:str(up_file)会把Django接收到的InMemoryUploadedFile对象转成类似<InMemoryUploadedFile: test.jpg (image/jpeg)>的字符串,这不是你本地的文件路径,直接拼接到upload_from_filename里会导致GCS尝试读取一个不存在的文件,或者错误地解析二进制内容为文本。
  2. 二进制文件的编码冲突:图片是二进制格式(比如JPG开头是0xff),当代码尝试用UTF-8解码这些二进制字节时,就会触发UnicodeDecodeError。

推荐解决方案:直接从文件对象上传(高效且避免本地存储)

修改你的上传函数,直接使用Django提供的文件对象上传到GCS,不需要保存到本地:

def post(self, request):
    up_file = request.data['file']
    print('******', request.data)
    
    # 初始化GCS客户端和Bucket
    client = storage.Client()
    bucket = client.bucket(settings.GOOGLE_CLOUD_STORAGE_BUCKET)
    
    # 用上传文件的原始文件名作为GCS中的Blob名称
    blob = bucket.blob(up_file.name)
    # 应用settings中配置的缓存控制规则
    blob.cache_control = settings.GOOGLE_CLOUD_STORAGE_DEFAULT_CACHE_CONTROL
    
    # 将文件指针移到开头(确保读取完整内容)
    up_file.seek(0)
    # 直接从文件对象上传,同时指定文件类型
    blob.upload_from_file(up_file, content_type=up_file.content_type)
    
    # 返回GCS中文件的公开访问URL(或者根据需求返回文件名)
    return Response(blob.public_url, status.HTTP_201_CREATED)

关键改进点:

  • 使用up_file.name获取上传文件的原始文件名,避免乱码和无效路径
  • upload_from_file直接读取请求中的文件流,无需本地存储,提升效率
  • 设置content_type让GCS正确识别文件类型,确保前端能正常访问图片
  • seek(0)确保文件指针回到起始位置,因为Django在解析请求时可能已经读取过文件内容

备选方案:先保存到本地再上传(不推荐)

如果你的业务逻辑必须先将文件保存到本地,需要用二进制模式写入文件,避免编码错误:

def post(self, request):
    up_file = request.data['file']
    print('******', request.data)
    
    # 定义本地保存路径,使用原始文件名
    local_file_path = f'C:/Users/tiwar/Downloads/{up_file.name}'
    
    # 用二进制模式写入文件,避免编码问题
    with open(local_file_path, 'wb') as f:
        for chunk in up_file.chunks():
            f.write(chunk)
    
    # 上传到GCS
    client = storage.Client()
    bucket = client.bucket(settings.GOOGLE_CLOUD_STORAGE_BUCKET)
    blob = bucket.blob(up_file.name)
    blob.cache_control = settings.GOOGLE_CLOUD_STORAGE_DEFAULT_CACHE_CONTROL
    blob.upload_from_filename(local_file_path, content_type=up_file.content_type)
    
    return Response(up_file.name, status.HTTP_201_CREATED)

额外注意事项

  • Postman配置:确保请求用form-data格式,键名为file,类型选择File,然后选择要上传的图片文件
  • GCS权限:确认你的服务账号拥有Storage Object Creator或更高权限,否则会出现上传权限错误
  • settings配置:你的DEFAULT_FILE_STORAGE配置是正确的,但如果用自定义上传函数,这个配置不会直接生效,需要手动设置cache_control等参数

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 12:29:05