파일처리-1에서처럼 하면 파일의 형식을 알 수 없습니다.
그래서 따로 파일 형식에 대해서 알 수 있도록 FastAPI에서 제공하는 방법이 있습니다.
바로 UploadFile을 이용하는 것입니다.
다음과 같이 main.py를 작성해 봅시다.
#UploadFile 이용하기
import uvicorn
from tempfile import NamedTemporaryFile
from typing import IO
from fastapi import FastAPI, File, UploadFile
app = FastAPI()
@app.post("/file/info")
def get_file_info(file: UploadFile = File(...)):
return {
"content_type": file.content_type,
"filename": file.filename
}
if __name__ == "__main__":
uvicorn.run("main:app", reload = True)
UploadFile을 사용하면, 입력된 파일의 content_type이라 던가 file의 이름을 알 수 있습니다.
다음 명령어로 main.py 파일을 실행시킨 후 FastAPI docs에 접속을 해봅시다. http://127.0.0.1:8000/docs
python main.py
접속하면 아래와 같은 화면이 나오는데, 여기에 try it out을 클릭해 봅시다.
지난 번과 동일하게 파일의 선택할 수 있게됩니다.
파일 선택을 클릭후에 아무 이미지나 선택해봅시다.
이미지를 선택한 후에 Execute를 눌러 실행해보면, 다음과 같은 결과가 나타납니다.
content_type과 file의 이름이 무엇인지를 알 수 있게 됩니다. 위와 같이 UploadFile에는 다양한 정보가 있는데, 재밌는 것은 기존 IO와 같은 메소드를 비동기로 지원합니다. 여기서 말하는 IO는 파이썬 표준 입출력 객체입니다.
어려운 말보다는open 내장 함수를 떠올리시면 됩니다.
- write
- read
- seek
- close
다만, 비동기 메소드들이므로 반드시 await 키워드와 함께 써야합니다. 그렇지 않으면 UploadFile.file 객체를 이용하면 됩니다. 흔히 말하는 file-like 객체입니다.
다음과 같이 사용할 수 있고 주의할 점은 함수 앞에 async 키워드가 붙는다는 걸 명심하셔야 합니다. 이제부터는 모든 함수에 async 키워드를 붙여 작성하겠습니다.
다음과 같이 main.py를 수정해 주시면 됩니다.
#UploadFile 이용하기
import uvicorn
from tempfile import NamedTemporaryFile
from typing import IO
from fastapi import FastAPI, File, UploadFile
app = FastAPI()
@app.post("/file/info")
async def get_file_info(file: UploadFile = File(...)):
file_like_obj = file.file
contents = await file.read()
return {
"content_type": file.content_type,
"filename": file.filename,
}
if __name__ == "__main__":
uvicorn.run("main:app", reload = True)
위의 코드에서 file.file이라는 것이 있는데, 이를 file-like 객체라고 부릅니다. file-like 객체란 파일과 유사한 특성을 갖는 객체를 의미하며, 객체들은 파일처럼 데이터를 읽고 쓸 수 있으며, 파일과 동일한 메서드와 속성을 가질 수 있습니다.
예를 들어, 일반 파일과 마찬가지로 파일과 유사한 객체에서 데이터를 읽어오거나 쓸 수 있습니다. 이러한 파일과 유사한 객체는 실제 파일이 아니더라도 파일과 유사한 동작을 수행할 수 있어서 파일과 유사한 환경에서 사용될 수 있습니다.
위의 코드에서 UploadFile을 사용할 경우, file-like 객체는 비동기 객체라고 생각하시면됩니다. 따라서 위의 코드는 비동기 적으로 돌아 갈 수 있는 코드가 됩니다.
다음으로는 파일을 위와 같이 불러온 후에 즉, 파일의 처리후에 저장하는 방법입니다.
요즘은 서버 자체에 저장을 하기보다는 아마존의 S3와 같은 스토리지 서버에 저장을 자주합니다.
다른 스토리지 서버에 저장을 하게 됩니다.
다음과 같이 main.py를 작성해 주세요
import uvicorn
from tempfile import NamedTemporaryFile
from typing import IO
from fastapi import FastAPI, File, UploadFile
app = FastAPI()
async def save_file(file: IO):
with NamedTemporaryFile("wb", delete=False) as tempfile:
tempfile.write(file.read())
return tempfile.name
@app.post("/file/store")
async def store_file(file:UploadFile = File(...)):
path = await save_file(file.file)
return {"filepath":path}
if __name__ == "__main__":
uvicorn.run("main:app", reload = True)
보통은 S3에 업로드를 하지만 여기서는 S3 업로드 대신 파일을 저장을 해보겠습니다.
우선 FastAPI docs(http://127.0.0.1:8000/docs)에 접속해봅시다. 접속한 후에 Try it out을 누른 후에 아무 파일이나 선택한고, Execute를 클릭해 봅시다.
그럼 위와 같이 filepath가 나타납니다. 위의 filepath는 tmp 폴더에 tmphzwmt_v4라는 파일이 저장 됐다는 의미입니다. 따라서 새로운 터미널을 열여서 tmp 폴더로 이동해서 해당 파일이 저장 되었는지 확인해 보겠습니다.
cd /tmp/
ls | grep tmphzwmt_v4
위에서 결과처럼 잘 저장이 되어져 있는 것을 확인할 수 있습니다.
'FastAPI' 카테고리의 다른 글
의존성 주입 - 1 (1) | 2024.02.15 |
---|---|
에러처리 (0) | 2024.02.15 |
파일처리 - 1 (0) | 2024.02.10 |
Form 데이터 (0) | 2024.02.05 |
RDB 연동 - 4 (0) | 2024.02.04 |