如何从外部 API 重新传输响应?

问题描述 投票:0回答:1

想象有一个简单的 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
可以不同。我无法对它们进行硬编码。

fastapi starlette
1个回答
0
投票

如果您想从响应中获得

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
            )
© www.soinside.com 2019 - 2024. All rights reserved.