Skip to content

19. Request Files


1. Request Files

  • File을 사용하여 클라이언트가 업로드할 파일을 정의할 수 있다.


Note

  • 업로드된 파일을 받기 위해서는 먼저, $ pip install python-multipart를 통해 python-multipart를 설치해야 한다.


2. Import File

  • 먼저, fastapiFileUploadFile을 임포트한다.


from fastapi import FastAPI, File, UploadFile

app = FastAPI()

@app.post("/files/")
async def create_file(file: bytes = File(...)):
    return {"file_size": len(file)}

@app.post("/uploadfile/")
async def create_upload_file(file: UploadFile = File(...)):
    return {"filename": file.filename}


3. Define File parameters

  • Body 또는 Form과 마찬가지로 file 매개변수를 생성한다.


from fastapi import FastAPI, File, UploadFile

app = FastAPI()

@app.post("/files/")
async def create_file(file: bytes = File(...)):
    return {"file_size": len(file)}

@app.post("/uploadfile/")
async def create_upload_file(file: UploadFile = File(...)):
    return {"filename": file.filename}


Note

  • file bodies를 선언하려면 File을 사용해야 한다.
  • 그 이유는 매개변수가 query 매개변수 또는 JSON body로 해석되기 때문이다.


  • 파일은 "form data"로 업로드된다.
  • path operation function 매개변수의 타입을 bytes로 선언하면, FastAP가 파일을 읽고 내용을 bytes로 받게 된다.
  • 이를 실행하는 경우 전체 내용이 메모리에 저장된다는 것을 의미하는데, 이러한 이유로 작은 파일에서 잘 작동한다.
  • 그러나 다른 경우 UploadFile을 사용하는 게 더 좋다.


4. File parameters with UploadFile

  • File 매개변수를 UploadFile 타입으로 정의한다.


from fastapi import FastAPI, File, UploadFile

app = FastAPI()

@app.post("/files/")
async def create_file(file: bytes = File(...)):
    return {"file_size": len(file)}

@app.post("/uploadfile/")
async def create_upload_file(file: UploadFile = File(...)):
    return {"filename": file.filename}


  • UploadFile을 사용하면 bytes에 비해 다음과 같은 장점을 가진다.


1] 스풀링된 파일을 사용한다.

  • 이것은 최대 크기 제한까지 메모리에 저장된 파일이며, 이 제한을 초과하면 디스크에 저장된다.
  • 즉, 모든 메모리를 소비하지 않고도 이미지, 비디오, 대용량 바이너리 등과 같은 대용량 파일에서 잘 작동한다.

2] 업로드된 파일에서 메타데이터를 얻을 수 있다.

3] file-like 객체인 async 인터페이스를 가진다.

4] file-like 객체를 기대하는 다른 라이브러리에 직접 전달할 수 있는 실제 Python SpooledTemporaryFile 객체를 노출한다.


1) UploadFile

  • UploadFile은 다음과 같은 속성을 가진다.


1] filename

  • str 타입의 업로드된 원본 파일 이름(myimage.jpg)이다.

2] content_type

  • str 타입의 콘텐츠 타입(MIME 타입/media 타입)(image/jpeg)이다.

3] file

  • 다른 라이브러리에 직접 전달될 수 있는 file-like 객체인 SpooledTemporaryFile이다.


  • UploadFile은 다음과 같은 async 메소드를 가진다.


1] write(data)

  • data(str 타입 또는 bytes 타입)를 파일에 쓴다.

2] read(size)

  • 파일의 bytes/characters size(int 타입)를 읽는다.

3] seek(offset)

  • 파일의 byte 위치 offset(int 타입)으로 이동한다.
  • 예를 들어, await myfile.seek(0)의 경우 파일의 시작 지점으로 이동한다.
  • 이것은 await myfile.read()를 한 번 실행한 다음 내용을 다시 읽어야 하는 경우 유용하다.

4] close()

  • 파일을 닫는다.


  • 이러한 모든 메소드는 async 메소드이므로 "await"해야 한다.


  • 예를 들어, async path operation function 내부에서 다음과 같이 내용을 가져올 수 있다.


contents = await myfile.read()


  • 만약 일반적인 def path operation function 내부에 있는 경우, 다음과 같이 UploadFile.file에 직접 접근할 수 있다. br
contents = myfile.file.read()


5. What is "Form Data"

  • HTML forms(<form></form>)가 서버에 데이터를 보낼 때는 JSON과 다른 특수 인코딩을 사용한다.


Note

  • forms의 데이터는 일반적으로 "media type"인 application/x-www-form-urlencoded를 사용하여 인코딩된다.
  • 하지만 form에 파일이 포함된 경우 multipart/form-data로 인코딩된다.
  • 이와 같은 인코딩 및 form fields에 대해 자세히 알아보려면 POST에 대한 MDN 웹 문서를 확인하면 된다.


  • path operation에서 여러 FileForm 매개변수를 선언할 수 있다.
  • 하지만 이 경우 request에 application/json 대신 application/x-www-form-urlencoded를 사용하여 인코딩된 body가 있기 때문에 JSON의 형식으로 받는 Body fields는 선언할 수 없다.


6. Multiple file uploads

  • 여러 파일을 동시에 업로드할 수 있다.
  • 이 파일들은 "form data"를 사용하여 보낸 동일한 "form field"에 연결된다.


  • 다음의 예제는 bytesList 또는 UploadFile을 선언하여 여러 파일을 동시에 업로드하는 예제이다.


from typing import List
from fastapi import FastAPI, File, UploadFile
from fastapi.responses import HTMLResponse

app = FastAPI()

@app.post("/files/")
async def create_files(files: List[bytes] = File(...)):
    return {"file_sizes": [len(file) for file in files]}

@app.post("/uploadfiles/")
async def create_upload_files(files: List[UploadFile] = File(...)):
    return {"filenames": [file.filename for file in files]}

@app.get("/")
async def main():
    content = """
<body>
<form action="/files/" enctype="multipart/form-data" method="post">
<input name="files" type="file" multiple>
<input type="submit">
</form>
<form action="/uploadfiles/" enctype="multipart/form-data" method="post">
<input name="files" type="file" multiple>
<input type="submit">
</form>
</body>
    """

    return HTMLResponse(content=content)

References