I am using FastAPI to upload a file according to the official documentation, as shown below:
@app.post("/create_file/")
async def create_file(file: UploadFile = File(...)):
file2store = await file.read()
# some code to store the BytesIO(file2store) to the other database
When I send a request using Python requests library, as shown below:
f = open(".../file.txt", 'rb')
files = {"file": (f.name, f, "multipart/form-data")}
requests.post(url="SERVER_URL/create_file", files=files)
the file2store
variable is always empty. Sometimes (rarely seen), it can get the file bytes, but almost all the time it is empty, so I can't restore the file on the other database.
I also tried the bytes
rather than UploadFile
, but I get the same results. Is there something wrong in my code, or is the way I use FastAPI to upload a file wrong?
Note that the answer below uses synchronous writing for writing the files to disk. If you need async writing, please have a look at this answer . Moreover, if you need to send additional data (such as JSON
data) together with uploading the file(s), please have a look at this answer . I would suggest you have a look at this answer as well, which explains the difference between defining an endpoint with def
and async def
, and demonstrates how to read the contents
of an uploaded file when using def
(if that's a requirement for your app).
app.py
import uvicorn
from fastapi import File, UploadFile, FastAPI
app = FastAPI()
@app.post("/upload")
async def upload(file: UploadFile = File(...)):
try:
contents = await file.read()
with open(file.filename, 'wb') as f:
f.write(contents)
except Exception:
return {"message": "There was an error uploading the file"}
finally:
await file.close()
return {"message": f"Successfuly uploaded {file.filename}"}
if __name__ == '__main__':
uvicorn.run(app, host='0.0.0.0', port=8000)
test.py
import requests
url = 'http://127.0.0.1:8000/upload'
file = {'file': open('images/1.png', 'rb')}
resp = requests.post(url=url, files=file)
print(resp.json())
app.py
import uvicorn
from fastapi import File, UploadFile, FastAPI
from typing import List
app = FastAPI()
@app.post("/upload")
async def upload(files: List[UploadFile] = File(...)):
for file in files:
try:
contents = await file.read()
with open(file.filename, 'wb') as f:
f.write(contents)
except Exception:
return {"message": "There was an error uploading the file(s)"}
finally:
await file.close()
return {"message": f"Successfuly uploaded {[file.filename for file in files]}"}
if __name__ == '__main__':
uvicorn.run(app, host='0.0.0.0', port=8000)
test.py
import requests
url = 'http://127.0.0.1:8000/upload'
files = [('files', open('images/1.png', 'rb')), ('files', open('images/2.png', 'rb'))]
resp = requests.post(url=url, files=files)
print(resp.json())
@app.post("/create_file/")
async def image(image: UploadFile = File(...)):
print(image.file)
# print('../'+os.path.isdir(os.getcwd()+"images"),"*************")
try:
os.mkdir("images")
print(os.getcwd())
except Exception as e:
print(e)
file_name = os.getcwd()+"/images/"+image.filename.replace(" ", "-")
with open(file_name,'wb+') as f:
f.write(image.file.read())
f.close()
file = jsonable_encoder({"imagePath":file_name})
new_image = await add_image(file)
return {"filename": new_image}
Just copy and paste the code it will work perfect.
from fastapi import (
FastAPI
UploadFile,
File,
status
)
from fastapi.responses import JSONResponse
import aiofiles
app = FastAPI( debug = True )
@app.post("/upload_file/", response_description="", response_model = "")
async def result(file:UploadFile = File(...)):
try:
async with aiofiles.open(file.filename, 'wb') as out_file:
content = await file.read() # async read
await out_file.write(content) # async write
except Exception as e:
return JSONResponse(
status_code = status.HTTP_400_BAD_REQUEST,
content = { 'message' : str(e) }
)
else:
return JSONResponse(
status_code = status.HTTP_200_OK,
content = {"result":'result'}
)
I had worked on it nearly 7-8 months ago, I didn't encounter the problem which you are saying. I had found out that that UploadFile is of type SpooledTemproaryFile and I didn't try reading file asynchronously. Here is the snippet which is being used. I have uploaded all types of files up to 100mb, it is working. I had to save file on server on a specific path
with open(path, 'wb') as f:
[f.write(chunk) for chunk in iter(lambda: file.file.read(10000), b'')]
In your case I'd suggest reading file and making the post request directly using aiohttp sessions or AsyncClient from httpx
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.