通过AWS API Gateway+Python Mangum返回二进制响应失败求助
关于Mangum二进制响应配置的问题
我按照Mangum文档中二进制响应的默认配置说明操作,但始终无法实现二进制响应功能,客户端收到的一直是base64编码的数据。我的理解是Mangum应该自动识别非text_mime_types的Content-Type,将响应的isBase64Encoded设为true,让API Gateway转换为二进制数据返回给客户端,但实际没生效。
我的代码如下:
import random from fastapi import APIRouter, Response from fastapi.middleware.gzip import GZipMiddleware router = APIRouter(tags=['public']) app = create_app() app.add_middleware(GZipMiddleware, minimum_size=1000) # AWS Lambda support handler = Mangum(app, lifespan="off") @router.get("/update/{current_state}/download") async def download_something_binary() -> Response: # Create some random bytes import random open('/tmp/data', 'wb').write(random.randbytes(1024 * 100)) # Return the binary payload f = open('/tmp/data', 'rb') return Response( status_code=200, content=f.read(), headers={ "Content-Type": "application/octet-stream", "Content-Disposition": "attachment; filename=data.tar.gz"})
我还尝试过直接返回字典,但结果还是一样。请问是我的理解有误还是操作出错?
排查与解决要点
检查Mangum版本
旧版本的Mangum在二进制响应处理上可能存在问题,确保使用最新稳定版:pip install --upgrade mangum显式配置二进制MIME类型
避免自动识别的偏差,直接指定binary_mime_types:handler = Mangum( app, lifespan="off", binary_mime_types=["application/octet-stream"] )或者从默认文本类型中排除对应类型:
handler = Mangum( app, lifespan="off", text_mime_types=Mangum.DEFAULT_TEXT_MIME_TYPES - {"application/octet-stream"} )配置API Gateway二进制媒体类型
即使Mangum设置了isBase64Encoded,API Gateway也需同步配置:- 进入API Gateway控制台,选择目标API
- 切换到设置选项卡,在二进制媒体类型中添加
application/octet-stream - 重新部署API使配置生效
排查GZip中间件的影响
GZip压缩可能干扰Mangum的二进制识别逻辑,可先移除中间件测试,若正常再调整:- 针对该路由禁用GZip(FastAPI 0.95+支持)
@router.get( "/update/{current_state}/download", responses={200: {"content": {"application/octet-stream": {}}}}, middleware=[{"middleware_class": GZipMiddleware, "minimum_size": 1000, "exclude_paths": ["/update/{current_state}/download"]}] )- 或在响应中添加
Vary头避免缓存问题
修复文件操作的资源泄漏
使用with语句确保文件正确关闭,避免读取不完整:async def download_something_binary() -> Response: # 生成随机字节 with open('/tmp/data', 'wb') as f: f.write(random.randbytes(1024 * 100)) # 读取并返回二进制内容 with open('/tmp/data', 'rb') as f: content = f.read() return Response( status_code=200, content=content, headers={ "Content-Type": "application/octet-stream", "Content-Disposition": "attachment; filename=data.tar.gz" } )
内容的提问来源于stack exchange,提问作者Jakob Simon-Gaarde
相关产品推荐
相关产品推荐

