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

使用smart-open读取S3文件结合FileResponse下载报错的解决咨询

解决S3文件通过smart-open与Django FileResponse结合的下载问题

问题说明

要实现网页端下载存储在S3桶中的文件(支持.txt、.pdf、.doc/.docx),使用smart-open访问S3资源时,结合Django的FileResponse出现报错:TypeError: expected str, bytes or os.PathLike object, not Reader。原代码尝试对smart-open返回的Reader对象再次调用open(),导致类型不匹配。

原错误代码:

@api_view(['GET'])
def download_attachment(request, pk):
    session = boto3.Session(aws_access_key_id=AWS_ACCESS_KEY_ID,
                            aws_secret_access_key=AWS_SECRET_ACCESS_KEY)
    obj = Attachment.objects.get(id=pk)
    with smart_opener(f's3://______media/public/{str(obj)}',"rb",transport_params={'client':session.client('s3')}) as attachment:
        response = FileResponse(open(attachment, 'rb'))  # 错误:对已打开的Reader调用open()
    response['Content-Disposition'] = f'attachment; filename={obj.file.name}'
    return response

解决方案

smart-open的with上下文管理器已经返回了一个可读取的文件对象(Reader),直接将其传入FileResponse即可,无需再次调用open()。同时建议添加正确的Content-Type头,让浏览器能识别文件类型:

import mimetypes
from django.http import FileResponse
from rest_framework.decorators import api_view
import boto3
from smart_open import open as smart_opener

@api_view(['GET'])
def download_attachment(request, pk):
    session = boto3.Session(aws_access_key_id=AWS_ACCESS_KEY_ID,
                            aws_secret_access_key=AWS_SECRET_ACCESS_KEY)
    obj = Attachment.objects.get(id=pk)
    s3_path = f's3://______media/public/{str(obj)}'
    
    # 获取文件MIME类型,用于设置Content-Type
    mime_type, _ = mimetypes.guess_type(obj.file.name)
    mime_type = mime_type or 'application/octet-stream'  # 兜底类型
    
    with smart_opener(s3_path, "rb", transport_params={'client': session.client('s3')}) as attachment:
        response = FileResponse(attachment)
    
    # 设置下载头和类型
    response['Content-Disposition'] = f'attachment; filename="{obj.file.name}"'
    response['Content-Type'] = mime_type
    
    return response

关键修改点

  • 移除错误的open(attachment, 'rb'),直接传递smart-open返回的文件对象给FileResponse
  • 新增Content-Type头,通过mimetypes模块自动识别文件类型,提升浏览器处理兼容性
  • 给文件名添加双引号,避免文件名包含空格或特殊字符时出现解析问题

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 03:10:34