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

Django上传文件到AWS S3报ValueError: Filename must be a string如何解决

问题原因

你调用的boto3 S3客户端的upload_file()方法,第一个入参要求是本地文件的路径字符串,而非文件句柄对象。你代码中传入了open(img_path, 'rb')得到的文件对象fp,不符合方法入参要求,因此触发ValueError: Filename must be a string报错。

解决方案

提供两种可选修复方式,按需选择即可:

方案1:直接传入本地文件路径(推荐,代码更简洁)

你已经将图片保存到了本地路径img_path,无需额外打开文件,直接将路径作为第一个参数传入upload_file()即可,修改对应代码段为:

try:
    # 删掉原有with open打开文件的逻辑,直接传本地路径字符串
    response = s3_client.upload_file(img_path, 'etp-tms', 'image_0.jpg')
except ClientError as e:
    print(e)

方案2:替换为支持文件对象的上传方法

如果你确实需要通过文件句柄上传,将方法替换为upload_fileobj()即可,该方法支持传入文件对象作为第一个参数:

try:
    with open(img_path, 'rb') as fp:
        # 把upload_file改为upload_fileobj
        response = s3_client.upload_fileobj(fp, 'etp-tms', 'image_0.jpg')
except ClientError as e:
    print(e)
额外优化建议

如果你的业务不需要在服务器本地留存图片备份,可以直接省略写入本地磁盘的步骤,直接将Django拿到的上传文件对象传入S3,性能更高:

def save_pic(request):
    print("save_pic")
    data = {'state': 0}
    if request.method == 'POST':
        image = request.FILES.get('image')
        if not image:
            return JsonResponse(data)
        import boto3
        from botocore.exceptions import ClientError
        s3_client = boto3.client('s3', aws_access_key_id='XXX',
        aws_secret_access_key='XXX', region_name='XXX')
        try:
            # 直接上传文件对象,无需本地存盘,可自定义S3端存储的文件名
            s3_client.upload_fileobj(image, 'etp-tms', f'image_{image.name}')
            data['state'] = 1
        except ClientError as e:
            print(e)
        return JsonResponse(data)
    return JsonResponse(data="fail", safe=False)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 18:27:03