想象有一个简单的 FastAPI 应用程序,它有一个单一的路由来重新传输来自外部 API 的文件响应:
from fastapi import FastAPI
app = FastAPI()
@app.get(
"/download",
response_class=FileResponse,
responses={
200: {"content": {"application/octet-stream": {}}, "description": "File"},
},
)
async def download():
async def iterfile():
url = "http://external-api:8000/api/v1/attachments-archive/download?id__in=d6ace33a-c068-45ac-8e7c-60f30f262e09"
async with AsyncClient() as client:
async with client.stream("GET", url) as resp:
# resp.headers returns:
# headers = {
# 'content-disposition': "attachment;filename*=UTF-8''archive-2024-10-03T21%3A28%3A13.597138.zip",
# 'content-type': 'application/x-zip-compressed',
# ... another headers
# }
async for chunk in resp.aiter_bytes():
yield chunk
return StreamingResponse(iterfile())
# but I need to specify (copy from resp) headers and media_type like this
# return StreamingResponse(
# iterfile(),
# headers={'content-disposition': "attachment;filename*=UTF-8''archive-2024-10-03T21%3A28%3A13.597138.zip"},
# media_type='application/x-zip-compressed'
# )
外部 API 返回 zip 存档。我需要重新播放它。为了从我的应用程序流式传输响应,我使用 StreamingResponse。
主要的困难是为 StreamingResponse 指定
headers
和 media_type
。我怎样才能先获取这些值,然后获取 iterfile()
流?
附注
headers
和 media_type
可以不同。我无法对它们进行硬编码。
如果您想从响应中获得
headers
和 media_type
,这样的操作应该有效:
async def download():
url = "http://external-api:8000/api/v1/attachments-archive/download?id__in=d6ace33a-c068-45ac-8e7c-60f30f262e09"
async with AsyncClient() as client:
async with client.stream("GET", url) as resp:
headers = {
'content-disposition': resp.headers.get('content-disposition'),
'content-type': resp.headers.get('content-type')
}
media_type = resp.headers.get('content-type', 'application/octet-stream')
async def iterfile():
async for chunk in resp.aiter_bytes():
yield chunk
return StreamingResponse(
iterfile(),
headers=headers,
media_type=media_type
)