Aber erinnern Sie sich, dass, wenn Sie Query, Path, File und andere von fastapi importieren, diese tatsächlich Funktionen sind, welche spezielle Klassen zurückgeben
Tipp
Um Dateibodys zu deklarieren, müssen Sie File verwenden, da diese Parameter sonst als Query-Parameter oder Body(-JSON)-Parameter interpretiert werden würden.
Die Dateien werden als „Formulardaten“ hochgeladen.
Wenn Sie den Typ Ihrer Pfadoperation-Funktion als bytes deklarieren, wird FastAPI die Datei für Sie auslesen, und Sie erhalten den Inhalt als bytes.
Bedenken Sie, dass das bedeutet, dass sich der gesamte Inhalt der Datei im Arbeitsspeicher befindet. Das wird für kleinere Dateien gut funktionieren.
Aber es gibt viele Fälle, in denen Sie davon profitieren, UploadFile zu verwenden.
UploadFile zu verwenden, hat mehrere Vorzüge gegenüber bytes:
Sie müssen File() nicht als Parameter-Defaultwert verwenden.
Es wird eine „Spool“-Datei verwendet:
Eine Datei, die bis zu einem bestimmten Größen-Limit im Arbeitsspeicher behalten wird, und wenn das Limit überschritten wird, auf der Festplatte gespeichert wird.
Das bedeutet, es wird für große Dateien wie Bilder, Videos, große Binärdateien, usw. gut funktionieren, ohne den ganzen Arbeitsspeicher aufzubrauchen.
Sie können Metadaten aus der hochgeladenen Datei auslesen.
Es stellt ein tatsächliches Python-SpooledTemporaryFile-Objekt bereit, welches Sie direkt anderen Bibliotheken übergeben können, die ein dateiartiges Objekt erwarten.
filename: Ein str mit dem ursprünglichen Namen der hochgeladenen Datei (z. B. meinbild.jpg).
content_type: Ein str mit dem Inhaltstyp (MIME-Typ / Medientyp) (z. B. image/jpeg).
file: Ein SpooledTemporaryFile (ein file-like Objekt). Das ist das tatsächliche Python-Objekt, das Sie direkt anderen Funktionen oder Bibliotheken übergeben können, welche ein „file-like“-Objekt erwarten.
UploadFile hat die folgenden asynchronen Methoden. Sie alle rufen die entsprechenden Methoden des darunterliegenden Datei-Objekts auf (wobei intern SpooledTemporaryFile verwendet wird).
write(daten): Schreibt daten (str oder bytes) in die Datei.
read(anzahl): Liest anzahl (int) bytes/Zeichen aus der Datei.
seek(versatz): Geht zur Position versatz (int) in der Datei.
Z. B. würde await myfile.seek(0) zum Anfang der Datei gehen.
Das ist besonders dann nützlich, wenn Sie await myfile.read() einmal ausführen und dann diese Inhalte erneut auslesen müssen.
close(): Schließt die Datei.
Da alle diese Methoden asynchron sind, müssen Sie sie awaiten („erwarten“).
Zum Beispiel können Sie innerhalb einer asyncPfadoperation-Funktion den Inhalt wie folgt auslesen:
contents=awaitmyfile.read()
Wenn Sie sich innerhalb einer normalen def-Pfadoperation-Funktion befinden, können Sie direkt auf UploadFile.file zugreifen, zum Beispiel:
contents=myfile.file.read()
Technische Details zu async
Wenn Sie die async-Methoden verwenden, führt FastAPI die Datei-Methoden in einem Threadpool aus und erwartet sie.
Technische Details zu Starlette
FastAPIs UploadFile erbt direkt von Starlettes UploadFile, fügt aber ein paar notwendige Teile hinzu, um es kompatibel mit Pydantic und anderen Teilen von FastAPI zu machen.
HTML-Formulare (<form></form>) senden die Daten in einer „speziellen“ Kodierung zum Server, welche sich von JSON unterscheidet.
FastAPI stellt sicher, dass diese Daten korrekt ausgelesen werden, statt JSON zu erwarten.
Technische Details
Daten aus Formularen werden, wenn es keine Dateien sind, normalerweise mit dem „media type“ application/x-www-form-urlencoded kodiert.
Sollte das Formular aber Dateien enthalten, dann werden diese mit multipart/form-data kodiert. Wenn Sie File verwenden, wird FastAPI wissen, dass es die Dateien vom korrekten Teil des Bodys holen muss.
Wenn Sie mehr über Formularfelder und ihre Kodierungen lesen möchten, besuchen Sie die MDN-Webdokumentation für POST.
Achtung
Sie können mehrere File- und Form-Parameter in einer Pfadoperation deklarieren, aber Sie können nicht gleichzeitig auch Body-Felder deklarieren, welche Sie als JSON erwarten, da der Request den Body mittels multipart/form-data statt application/json kodiert.
Das ist keine Limitation von FastAPI, sondern Teil des HTTP-Protokolls.
Sie können auch File() zusammen mit UploadFile verwenden, um zum Beispiel zusätzliche Metadaten zu setzen:
fromtypingimportAnnotatedfromfastapiimportFastAPI,File,UploadFileapp=FastAPI()@app.post("/files/")asyncdefcreate_file(file:Annotated[bytes,File(description="A file read as bytes")]):return{"file_size":len(file)}@app.post("/uploadfile/")asyncdefcreate_upload_file(file:Annotated[UploadFile,File(description="A file read as UploadFile")],):return{"filename":file.filename}
fromfastapiimportFastAPI,File,UploadFilefromtyping_extensionsimportAnnotatedapp=FastAPI()@app.post("/files/")asyncdefcreate_file(file:Annotated[bytes,File(description="A file read as bytes")]):return{"file_size":len(file)}@app.post("/uploadfile/")asyncdefcreate_upload_file(file:Annotated[UploadFile,File(description="A file read as UploadFile")],):return{"filename":file.filename}
Tipp
Bevorzugen Sie die Annotated-Version, falls möglich.
fromfastapiimportFastAPI,File,UploadFileapp=FastAPI()@app.post("/files/")asyncdefcreate_file(file:bytes=File(description="A file read as bytes")):return{"file_size":len(file)}@app.post("/uploadfile/")asyncdefcreate_upload_file(file:UploadFile=File(description="A file read as UploadFile"),):return{"filename":file.filename}
Sie erhalten, wie deklariert, eine liste von bytes oder UploadFiles.
Technische Details
Sie können auch from starlette.responses import HTMLResponse verwenden.
FastAPI bietet dieselben starlette.responses auch via fastapi.responses an, als Annehmlichkeit für Sie, den Entwickler. Die meisten verfügbaren Responses kommen aber direkt von Starlette.