Ana içeriğe geç

Request Dosyaları

🌐 Yapay Zekâ ve İnsanlar Tarafından Çeviri

Bu çeviri, insanlar tarafından yönlendirilen bir yapay zekâ ile oluşturuldu. 🤝

Orijinal anlamın yanlış anlaşılması ya da kulağa doğal gelmeme gibi hatalar içerebilir. 🤖

Yapay zekâyı daha iyi yönlendirmemize yardımcı olarak bu çeviriyi iyileştirebilirsiniz.

İngilizce sürüm

İstemcinin upload edeceği dosyaları File kullanarak tanımlayabilirsiniz.

Bilgi

Upload edilen dosyaları alabilmek için önce python-multipart yükleyin.

Bir virtual environment oluşturduğunuzdan, aktive ettiğinizden ve ardından paketi yüklediğinizden emin olun. Örneğin:

$ pip install python-multipart

Bunun nedeni, upload edilen dosyaların "form data" olarak gönderilmesidir.

File Import Edin

fastapi içinden File ve UploadFile import edin:

from typing import Annotated

from fastapi import FastAPI, File, UploadFile

app = FastAPI()


@app.post("/files/")
async def create_file(file: Annotated[bytes, File()]):
    return {"file_size": len(file)}


@app.post("/uploadfile/")
async def create_upload_file(file: UploadFile):
    return {"filename": file.filename}
🤓 Other versions and variants

Tip

Prefer to use the Annotated version if possible.

from fastapi import FastAPI, File, UploadFile

app = FastAPI()


@app.post("/files/")
async def create_file(file: bytes = File()):
    return {"file_size": len(file)}


@app.post("/uploadfile/")
async def create_upload_file(file: UploadFile):
    return {"filename": file.filename}

File Parametrelerini Tanımlayın

Body veya Form için yaptığınız gibi dosya parametreleri oluşturun:

from typing import Annotated

from fastapi import FastAPI, File, UploadFile

app = FastAPI()


@app.post("/files/")
async def create_file(file: Annotated[bytes, File()]):
    return {"file_size": len(file)}


@app.post("/uploadfile/")
async def create_upload_file(file: UploadFile):
    return {"filename": file.filename}
🤓 Other versions and variants

Tip

Prefer to use the Annotated version if possible.

from fastapi import FastAPI, File, UploadFile

app = FastAPI()


@app.post("/files/")
async def create_file(file: bytes = File()):
    return {"file_size": len(file)}


@app.post("/uploadfile/")
async def create_upload_file(file: UploadFile):
    return {"filename": file.filename}

Bilgi

File, doğrudan Form’dan türeyen bir sınıftır.

Ancak unutmayın: fastapi içinden Query, Path, File ve diğerlerini import ettiğinizde, bunlar aslında özel sınıflar döndüren fonksiyonlardır.

İpucu

File body’leri tanımlamak için File kullanmanız gerekir; aksi halde parametreler query parametreleri veya body (JSON) parametreleri olarak yorumlanır.

Dosyalar "form data" olarak upload edilir.

path operation function parametrenizin tipini bytes olarak tanımlarsanız, FastAPI dosyayı sizin için okur ve içeriği bytes olarak alırsınız.

Bunun, dosyanın tüm içeriğinin bellekte tutulacağı anlamına geldiğini unutmayın. Küçük dosyalar için iyi çalışır.

Ancak bazı durumlarda UploadFile kullanmak size fayda sağlayabilir.

UploadFile ile Dosya Parametreleri

Tipi UploadFile olan bir dosya parametresi tanımlayın:

from typing import Annotated

from fastapi import FastAPI, File, UploadFile

app = FastAPI()


@app.post("/files/")
async def create_file(file: Annotated[bytes, File()]):
    return {"file_size": len(file)}


@app.post("/uploadfile/")
async def create_upload_file(file: UploadFile):
    return {"filename": file.filename}
🤓 Other versions and variants

Tip

Prefer to use the Annotated version if possible.

from fastapi import FastAPI, File, UploadFile

app = FastAPI()


@app.post("/files/")
async def create_file(file: bytes = File()):
    return {"file_size": len(file)}


@app.post("/uploadfile/")
async def create_upload_file(file: UploadFile):
    return {"filename": file.filename}

UploadFile kullanmanın bytes’a göre birkaç avantajı vardır:

  • Parametrenin varsayılan değerinde File() kullanmak zorunda değilsiniz.
  • "Spooled" bir dosya kullanır:
    • Belirli bir maksimum boyuta kadar bellekte tutulan, bu limiti aşınca diske yazılan bir dosya.
  • Bu sayede görüntüler, videolar, büyük binary’ler vb. gibi büyük dosyalarda tüm belleği tüketmeden iyi çalışır.
  • Upload edilen dosyadan metadata alabilirsiniz.
  • file-like bir async arayüze sahiptir.
  • SpooledTemporaryFile nesnesini dışa açar; bunu, file-like nesne bekleyen diğer library’lere doğrudan geçebilirsiniz.

UploadFile

UploadFile şu attribute’lara sahiptir:

  • filename: Upload edilen orijinal dosya adını içeren bir str (örn. myimage.jpg).
  • content_type: Content type’ı (MIME type / media type) içeren bir str (örn. image/jpeg).
  • file: Bir SpooledTemporaryFile (bir file-like nesne). Bu, "file-like" nesne bekleyen diğer fonksiyonlara veya library’lere doğrudan verebileceğiniz gerçek Python file nesnesidir.

UploadFile şu async method’lara sahiptir. Bunların hepsi altta ilgili dosya method’larını çağırır (dahili SpooledTemporaryFile kullanarak).

  • write(data): Dosyaya data (str veya bytes) yazar.
  • read(size): Dosyadan size (int) kadar byte/karakter okur.
  • seek(offset): Dosyada offset (int) byte pozisyonuna gider.
    • Örn. await myfile.seek(0) dosyanın başına gider.
    • Bu, özellikle bir kez await myfile.read() çalıştırdıysanız ve sonra içeriği yeniden okumaya ihtiyaç duyuyorsanız faydalıdır.
  • close(): Dosyayı kapatır.

Bu method’ların hepsi async olduğundan, bunları "await" etmeniz gerekir.

Örneğin, bir async path operation function içinde içeriği şöyle alabilirsiniz:

contents = await myfile.read()

Normal bir def path operation function içindeyseniz UploadFile.file’a doğrudan erişebilirsiniz, örneğin:

contents = myfile.file.read()

async Teknik Detaylar

async method’ları kullandığınızda, FastAPI dosya method’larını bir threadpool içinde çalıştırır ve bunları await eder.

Starlette Teknik Detaylar

FastAPI’nin UploadFile’ı doğrudan Starlette’in UploadFile’ından türetilmiştir; ancak Pydantic ve FastAPI’nin diğer parçalarıyla uyumlu olması için bazı gerekli eklemeler yapar.

"Form Data" Nedir

HTML formları (<form></form>) veriyi server’a gönderirken normalde JSON’dan farklı, veri için "özel" bir encoding kullanır.

FastAPI, JSON yerine bu veriyi doğru yerden okuyacağından emin olur.

Teknik Detaylar

Formlardan gelen veri, dosya içermiyorsa normalde "media type" olarak application/x-www-form-urlencoded ile encode edilir.

Ancak form dosya içeriyorsa multipart/form-data olarak encode edilir. File kullanırsanız, FastAPI dosyaları body’nin doğru kısmından alması gerektiğini bilir.

Bu encoding’ler ve form alanları hakkında daha fazla okumak isterseniz MDN web dokümanlarındaki POST sayfasına bakın.

Uyarı

Bir path operation içinde birden fazla File ve Form parametresi tanımlayabilirsiniz, ancak JSON olarak almayı beklediğiniz Body alanlarını ayrıca tanımlayamazsınız; çünkü request body application/json yerine multipart/form-data ile encode edilmiş olur.

Bu, FastAPI’nin bir kısıtı değildir; HTTP protocol’ünün bir parçasıdır.

Opsiyonel Dosya Upload

Standart type annotation’ları kullanıp varsayılan değeri None yaparak bir dosyayı opsiyonel hale getirebilirsiniz:

from typing import Annotated

from fastapi import FastAPI, File, UploadFile

app = FastAPI()


@app.post("/files/")
async def create_file(file: Annotated[bytes | None, File()] = None):
    if not file:
        return {"message": "No file sent"}
    else:
        return {"file_size": len(file)}


@app.post("/uploadfile/")
async def create_upload_file(file: UploadFile | None = None):
    if not file:
        return {"message": "No upload file sent"}
    else:
        return {"filename": file.filename}
🤓 Other versions and variants
from typing import Annotated, Union

from fastapi import FastAPI, File, UploadFile

app = FastAPI()


@app.post("/files/")
async def create_file(file: Annotated[Union[bytes, None], File()] = None):
    if not file:
        return {"message": "No file sent"}
    else:
        return {"file_size": len(file)}


@app.post("/uploadfile/")
async def create_upload_file(file: Union[UploadFile, None] = None):
    if not file:
        return {"message": "No upload file sent"}
    else:
        return {"filename": file.filename}

Tip

Prefer to use the Annotated version if possible.

from fastapi import FastAPI, File, UploadFile

app = FastAPI()


@app.post("/files/")
async def create_file(file: bytes | None = File(default=None)):
    if not file:
        return {"message": "No file sent"}
    else:
        return {"file_size": len(file)}


@app.post("/uploadfile/")
async def create_upload_file(file: UploadFile | None = None):
    if not file:
        return {"message": "No upload file sent"}
    else:
        return {"filename": file.filename}

Tip

Prefer to use the Annotated version if possible.

from typing import Union

from fastapi import FastAPI, File, UploadFile

app = FastAPI()


@app.post("/files/")
async def create_file(file: Union[bytes, None] = File(default=None)):
    if not file:
        return {"message": "No file sent"}
    else:
        return {"file_size": len(file)}


@app.post("/uploadfile/")
async def create_upload_file(file: Union[UploadFile, None] = None):
    if not file:
        return {"message": "No upload file sent"}
    else:
        return {"filename": file.filename}

Ek Metadata ile UploadFile

Ek metadata ayarlamak için UploadFile ile birlikte File() da kullanabilirsiniz. Örneğin:

from typing import Annotated

from fastapi import FastAPI, File, UploadFile

app = FastAPI()


@app.post("/files/")
async def create_file(file: Annotated[bytes, File(description="A file read as bytes")]):
    return {"file_size": len(file)}


@app.post("/uploadfile/")
async def create_upload_file(
    file: Annotated[UploadFile, File(description="A file read as UploadFile")],
):
    return {"filename": file.filename}
🤓 Other versions and variants

Tip

Prefer to use the Annotated version if possible.

from fastapi import FastAPI, File, UploadFile

app = FastAPI()


@app.post("/files/")
async def create_file(file: bytes = File(description="A file read as bytes")):
    return {"file_size": len(file)}


@app.post("/uploadfile/")
async def create_upload_file(
    file: UploadFile = File(description="A file read as UploadFile"),
):
    return {"filename": file.filename}

Birden Fazla Dosya Upload

Aynı anda birden fazla dosya upload etmek mümkündür.

Bu dosyalar, "form data" ile gönderilen aynı "form field" ile ilişkilendirilir.

Bunu kullanmak için bytes veya UploadFile listesini tanımlayın:

from typing import Annotated

from fastapi import FastAPI, File, UploadFile
from fastapi.responses import HTMLResponse

app = FastAPI()


@app.post("/files/")
async def create_files(files: Annotated[list[bytes], File()]):
    return {"file_sizes": [len(file) for file in files]}


@app.post("/uploadfiles/")
async def create_upload_files(files: list[UploadFile]):
    return {"filenames": [file.filename for file in files]}


@app.get("/")
async def main():
    content = """
<body>
<form action="/files/" enctype="multipart/form-data" method="post">
<input name="files" type="file" multiple>
<input type="submit">
</form>
<form action="/uploadfiles/" enctype="multipart/form-data" method="post">
<input name="files" type="file" multiple>
<input type="submit">
</form>
</body>
    """
    return HTMLResponse(content=content)
🤓 Other versions and variants

Tip

Prefer to use the Annotated version if possible.

from fastapi import FastAPI, File, UploadFile
from fastapi.responses import HTMLResponse

app = FastAPI()


@app.post("/files/")
async def create_files(files: list[bytes] = File()):
    return {"file_sizes": [len(file) for file in files]}


@app.post("/uploadfiles/")
async def create_upload_files(files: list[UploadFile]):
    return {"filenames": [file.filename for file in files]}


@app.get("/")
async def main():
    content = """
<body>
<form action="/files/" enctype="multipart/form-data" method="post">
<input name="files" type="file" multiple>
<input type="submit">
</form>
<form action="/uploadfiles/" enctype="multipart/form-data" method="post">
<input name="files" type="file" multiple>
<input type="submit">
</form>
</body>
    """
    return HTMLResponse(content=content)

Tanımladığınız gibi, bytes veya UploadFile’lardan oluşan bir list alırsınız.

Teknik Detaylar

from starlette.responses import HTMLResponse da kullanabilirsiniz.

FastAPI, geliştiriciye kolaylık olsun diye starlette.responses modülünü fastapi.responses olarak da sağlar. Ancak mevcut response’ların çoğu doğrudan Starlette’ten gelir.

Ek Metadata ile Birden Fazla Dosya Upload

Daha önce olduğu gibi, UploadFile için bile ek parametreler ayarlamak amacıyla File() kullanabilirsiniz:

from typing import Annotated

from fastapi import FastAPI, File, UploadFile
from fastapi.responses import HTMLResponse

app = FastAPI()


@app.post("/files/")
async def create_files(
    files: Annotated[list[bytes], File(description="Multiple files as bytes")],
):
    return {"file_sizes": [len(file) for file in files]}


@app.post("/uploadfiles/")
async def create_upload_files(
    files: Annotated[
        list[UploadFile], File(description="Multiple files as UploadFile")
    ],
):
    return {"filenames": [file.filename for file in files]}


@app.get("/")
async def main():
    content = """
<body>
<form action="/files/" enctype="multipart/form-data" method="post">
<input name="files" type="file" multiple>
<input type="submit">
</form>
<form action="/uploadfiles/" enctype="multipart/form-data" method="post">
<input name="files" type="file" multiple>
<input type="submit">
</form>
</body>
    """
    return HTMLResponse(content=content)
🤓 Other versions and variants

Tip

Prefer to use the Annotated version if possible.

from fastapi import FastAPI, File, UploadFile
from fastapi.responses import HTMLResponse

app = FastAPI()


@app.post("/files/")
async def create_files(
    files: list[bytes] = File(description="Multiple files as bytes"),
):
    return {"file_sizes": [len(file) for file in files]}


@app.post("/uploadfiles/")
async def create_upload_files(
    files: list[UploadFile] = File(description="Multiple files as UploadFile"),
):
    return {"filenames": [file.filename for file in files]}


@app.get("/")
async def main():
    content = """
<body>
<form action="/files/" enctype="multipart/form-data" method="post">
<input name="files" type="file" multiple>
<input type="submit">
</form>
<form action="/uploadfiles/" enctype="multipart/form-data" method="post">
<input name="files" type="file" multiple>
<input type="submit">
</form>
</body>
    """
    return HTMLResponse(content=content)

Özet

Request’te (form data olarak gönderilen) upload edilecek dosyaları tanımlamak için File, bytes ve UploadFile kullanın.