我想从FastAPI后端下载一个大文件(.tar.gz
)。在服务器端,我只是验证了文件路径,然后使用Starlette.FileResponse
返回整个文件,就像我在StackOverflow上看到的许多相关问题一样。
服务器端:
return FileResponse(path=file_name, media_type='application/octet-stream', filename=file_name)
之后,我遇到了以下错误:
File "/usr/local/lib/python3.10/dist-packages/fastapi/routing.py", line 149, in serialize_response
return jsonable_encoder(response_content)
File "/usr/local/lib/python3.10/dist-packages/fastapi/encoders.py", line 130, in jsonable_encoder
return ENCODERS_BY_TYPE[type(obj)](obj)
File "pydantic/json.py", line 52, in pydantic.json.lambda
UnicodeDecodeError: 'utf-8' codec can't decode byte 0x8b in position 1: invalid start byte
我也尝试使用 StreamingResponse
,但是得到了相同的错误。还有其他方法可以做到吗?
我的代码中使用了 StreamingResponse
:
@x.post("/download")
async def download(file_name=Body(), token: str | None = Header(default=None)):
file_name = file_name["file_name"]
# should be something like xx.tar
def iterfile():
with open(file_name,"rb") as f:
yield from f
return StreamingResponse(iterfile(),media_type='application/octet-stream')
好的,这是关于这个问题的更新。 我发现错误并没有发生在此API上,而是由此API进行的转发请求导致了错误。
@("/")
def f():
req = requests.post(url ="/download")
return req.content
如果我返回一个带有.tar
文件的StreamingResponse
,可能会出现编码问题。
使用 requests 时,请记得设置相同的媒体类型,这里是 media_type='application/octet-stream'
。这样就可以正常工作了!
return StreamingResponse(iterfile())
但是当下载tar文件时,我仍然收到错误消息:“无法解码任何json对象”。 - Yuqi Wangmedia_type='application/octet-stream'
来指示它是二进制数据吗?你有失败的示例代码吗? - MatsLindhyield from f
中,我发现这可能会使用大量的CPU。我该怎么解决呢?也许原因是块大小太小,导致大量文件操作?我能在这里增加块大小吗? - Yuqi Wang