I'm trying to create a function that let me select a file from input on the frontend, then pass the file to the backend FastAPI, and eventually upload the file to Azure Blob storage. My Frontend code is below:
//front end
async function handleSubmit(){
const formdata = new FormData();
formdata.append(
"file",
file[0],
)
const headers={'Content-Type': file[0].type}
await axios.post("/uploadfile",formdata,headers)
.then(function (response) {
console.log(response)
});
}
Backend FastAPI - two methods I tried
//Backend FastAPI
@app.post("/uploadfile") //currently using
async def create_upload_file(file: UploadFile):
name = file.filename
type = file.content_type
return uploadtoazure(file,name,type)
@app.post("/files") //another method I tried
async def create_file(file: bytes= File()):
await uploadtoazure(file)
And the uploadtoazure() function
//Backend uploadtoazure() function
async def uploadtoazure(f,n,t):
connect_str = ""//removed from sample code
blob_service_client = BlobServiceClient.from_connection_string(connect_str)
container_name = "notes"
file = f.read()
local_file_name = n
cnt_settings = ContentSettings(content_type=t)
blob_client = blob_service_client.get_blob_client(container=container_name, blob=local_file_name)
blob_client.upload_blob(file,cnt_settings)
The error kept coming at me and when I tried another method another new error prevents me from moving forward.
Some problem I'm aware:
blob_client.upload_blob()
only accept some types of files, in which the file type I passed in from API isn't one of it.- I used the sample code in https://fastapi.tiangolo.com/tutorial/request-files/In which I am not quite sure of the characteristic of the class
UploadFile
andFile()
. - When I use the method which the file passed to API is
file: bytes= File()
, the file type seems able to upload to the blob storage, however it does not have a content type or suffix, hence I think finding a way to pass in the content_type of the file could be another solution, but it was harder than I thought.
I hope there's enough information, I desperately need someone to clear my confusion. Thank you very much.
CodePudding user response:
You were pretty close, but there are some improvements. For example, you are using synchronous and asynchronous code together. This leads to confusing issues, such as not awaiting f.read()
while that is an async method. Also, you don't have to pass content type to the azure storage blob client, just leave that to Azure.
I would recommend to use the async version of the azure-storage-blob package.
I re-wrote it a little. The below will run as-is and is a full working example.
from fastapi import FastAPI, HTTPException, UploadFile
from azure.storage.blob.aio import BlobServiceClient
app = FastAPI()
@app.post("/uploadfile")
async def create_upload_file(file: UploadFile):
name = file.filename
type = file.content_type
return await uploadtoazure(file,name,type)
async def uploadtoazure(file: UploadFile,file_name: str,file_type:str):
connect_str = "HERE_YUOUR_CONNECTION_STRING"
blob_service_client = BlobServiceClient.from_connection_string(connect_str)
container_name = "stackoverflow"
async with blob_service_client:
container_client = blob_service_client.get_container_client(container_name)
try:
blob_client = container_client.get_blob_client(file_name)
f = await file.read()
await blob_client.upload_blob(f)
except Exception as e:
print(e)
return HTTPException(401, "Something went terribly wrong..")
return "{'did_it_work':'yeah it did!'}"
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=8000, )
Hope this clarifies some bits!