FastAPI를 사용하여 대용량 파일을 다운로드하는 방법은 무엇입니까?
Fast에서 대용량 파일()을 다운로드하려고 합니다API 백엔드. 서버 측에서는 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
나도 사용해봤지만, 같은 오류가 발생했다. 다른 방법은 없나요?
내 코드:
@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
그리고 여기서 파일을 반환하면 인코딩 문제가 발생했습니다.
요청을 사용할 때는 동일한 미디어 유형을 설정해야 합니다. 여기 있습니다. 효과가 있어요!
예를 들어, 다음과 같은 경우 속도가 다소 느릴 수 있습니다:
from fastapi import FastAPI
from fastapi.responses import StreamingResponse
some_file_path = 'large-video-file.mp4'
app = FastAPI()
@app.get('/')
def main():
def iterfile():
with open(some_file_path, mode='rb') as f:
yield from f
return StreamingResponse(iterfile(), media_type='video/mp4')
대신 지정된 청크 크기를 사용하여 파일을 읽을 수 있는 생성기를 만들 수 있으므로 프로세스 속도가 빨라집니다. 아래에서 예를 찾을 수 있습니다.
는 제너레이터 또는 일반 제너레이터/반복자를 사용하여 응답 본문을 스트리밍할 수 있습니다. /를 지원하지 않는 표준 메서드를 사용한 경우 정상적으로 제너레이터 기능을 선언해야 합니다. 그러나 FastAPI/Starlette는 전달한 제너레이터가 비동기인지 여부를 확인하기 때문에 비동기적으로 작동하며, 그렇지 않으면 별도의 스레드에서 생성기를 실행하여 t를 사용합니다모자가 기다리고 있다.
응답에 헤더를 설정하여 콘텐츠가 예상되는 것(예: 비디오, 오디오 파일 등)인지, 로컬로 저장되는 것(지정된 사용)인지 여부를 나타낼 수 있습니다.
(MIME 유형이라고도 함)의 경우 두 가지 기본 MIME 유형이 있습니다( 참조):
- 텍스트 파일의 기본값입니다. 텍스트 파일은 사람이 읽을 수 있어야 하며 이진 데이터를 포함해서는 안 된다.
- 다른 모든 경우에 대한 기본값입니다. 안.
질문에 나와 있는 것처럼 확장자가 있는 파일의 경우 와 다른 형식을 사용할 수도 있습니다. 그렇지 않으면 파일의 형식을 알 수 없는 경우 를 참조하십시오. 일반적인 MIME 유형 목록은 위의 링크된 설명서를 참조하십시오.
옵션 1 - 일반 제너레이터 사용
from fastapi import FastAPI
from fastapi.responses import StreamingResponse
CHUNK_SIZE = 1024 * 1024 # = 1MB - adjust the chunk size as desired
some_file_path = 'large_file.tar'
app = FastAPI()
@app.get('/')
def main():
def iterfile():
with open(some_file_path, 'rb') as f:
while chunk := f.read(CHUNK_SIZE):
yield chunk
headers = {'Content-Disposition': 'attachment; filename="large_file.tar"'}
return StreamingResponse(iterfile(), headers=headers, media_type='application/x-tar')
옵션 2 - 제너레이터 사용
from fastapi import FastAPI
from fastapi.responses import StreamingResponse
import aiofiles
CHUNK_SIZE = 1024 * 1024 # = 1MB - adjust the chunk size as desired
some_file_path = 'large_file.tar'
app = FastAPI()
@app.get('/')
async def main():
async def iterfile():
async with aiofiles.open(some_file_path, 'rb') as f:
while chunk := await f.read(CHUNK_SIZE):
yield chunk
headers = {'Content-Disposition': 'attachment; filename="large_file.tar"'}
return StreamingResponse(iterfile(), headers=headers, media_type='application/x-tar')
'개발하자' 카테고리의 다른 글
파일 선택기를 사용하여 플랫폼 파일을 파일로 만들기 (0) | 2023.10.24 |
---|---|
Jupyter/iPython에서 동적으로 플롯을 업데이트하는 현재 올바른 방법은 무엇입니까? (1) | 2023.10.23 |
인라인에서 null 값을 확인하고 타이프스크립트에서 오류를 던지는 방법은? (0) | 2023.10.22 |
Python poetry, 선택적 종속성 설치 (0) | 2023.10.21 |
기존 플러터 앱/프로젝트에 플랫폼을 추가하려면 어떻게 해야 합니까? (0) | 2023.10.21 |