I'm doing this angular tutorial. I'm trying to create a backend endpoint using python fastAPI that receives the data via HttpClient POST, but I'm struggling to do so. (angular 13.0.2, python 3.7, fastapi 0.70.0)
html template code:
<input type="file" (change)="onFileSelected($event)" #fileUpload>
<div >
{{fileName || "No file uploaded yet."}}
<button mat-mini-fab color="primary" (click)="fileUpload.click()">
<mat-icon>attach_file</mat-icon>
</button>
</div>
corresponding component ts code:
onFileSelected(event) {
const file: File = event.target.files[0]
console.log(`onFileSelected(${file.name})`)
if (file) {
this.fileName = file.name;
const formData = new FormData();
formData.append("thumbnail", file);
const upload$ = this.http.post("http://localhost:8000/thumbnail-upload", formData);
upload$.subscribe();
console.log("upload done?")
}
fastapi code: inpired by this
@app.post("/thumbnail-upload")
def create_file(file: UploadFile = File(...)):
print(file)
return {"file_size": len(file)}
There seems to be some OK communication going on, but I'm stuck here:
output from uvicorn server:
←[32mINFO←[0m: 127.0.0.1:18231 - "←[1mPOST /thumbnail-upload HTTP/1.1←[0m" ←[31m422 Unprocessable Entity←[0m
output in browser debug console:
zone.js:2863 POST http://localhost:8000/thumbnail-upload 422 (Unprocessable Entity)
core.mjs:6495 ERROR HttpErrorResponse {headers: HttpHeaders, status: 422, statusText: 'Unprocessable Entity', url: 'http://localhost:8000/thumbnail-upload', ok: false, …}
How do I need to implement the fastAPI endpoint to get this running? Disclaimer: I'm pretty new to angular/fastapi, if I forgot to include necessary information, pls. tell me what's missing ;)
CodePudding user response:
The body of the 422 error message will give you exactly what field is missing. From your code it seems to indicate that you're submitting the file under the thumbnail
name, but you're using the file
name in your FastAPI route. Since those two doesn't match, FastAPI doesn't find the file you're assuming is present. Either rename the form parameter to file
or rename the FastAPI argument to thumbnail
:
@app.post("/thumbnail-upload")
def create_file(thumbnail: UploadFile = File(...)):
print(thumbnail)
return {"file_size": len(thumbnail.file.read())}
The UploadFile
object also exposes file
to interact with the spooled file behind the scenes. Since it doesn't give you the bytes directly, I don't think calling len
on it will do what you expected it to do.