Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
126 changes: 126 additions & 0 deletions docs/en/tutorial/file-uploads.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
# File Uploads

FastHTTP supports multipart file uploads via the `files` parameter.

## Simple Upload

Pass bytes directly:

```python
from fasthttp import FastHTTP
from fasthttp.response import Response

app = FastHTTP()


@app.post(
url="https://api.example.com/upload",
files={"file": b"Hello, world!"},
)
async def upload(resp: Response) -> dict:
return resp.json()
```

## Upload with Filename and Content Type

Provide a tuple of `(filename, data, content_type)`:

```python
@app.post(
url="https://api.example.com/upload",
files={"file": ("report.csv", b"name,score\nAlice,95\n", "text/csv")},
)
async def upload_csv(resp: Response) -> dict:
return resp.json()
```

## Multiple Files

Pass a dictionary with multiple keys:

```python
@app.post(
url="https://api.example.com/upload",
files={
"avatar": ("photo.jpg", b"\xff\xd8\xff\xe0...", "image/jpeg"),
"document": ("resume.pdf", b"%PDF-1.4...", "application/pdf"),
},
)
async def upload_multi(resp: Response) -> dict:
return resp.json()
```

Or use a list to send multiple files under the same field name:

```python
@app.post(
url="https://api.example.com/upload",
files=[
("files", ("a.txt", b"content of a", "text/plain")),
("files", ("b.txt", b"content of b", "text/plain")),
],
)
async def upload_list(resp: Response) -> dict:
return resp.json()
```

## Upload with JSON

Combine `files` with `json` to send metadata alongside the file:

```python
@app.post(
url="https://api.example.com/upload",
json={"title": "My photo", "tags": ["nature"]},
files={"file": ("sunset.jpg", b"\xff\xd8\xff\xe0...", "image/jpeg")},
)
async def upload_with_meta(resp: Response) -> dict:
return resp.json()
```

## File Object

Pass an open file handle:

```python
@app.post(
url="https://api.example.com/upload",
files={"file": open("photo.jpg", "rb")},
)
async def upload_file(resp: Response) -> dict:
return resp.json()
```

## Path Object

Pass a `pathlib.Path`:

```python
from pathlib import Path

FILE = Path("photo.jpg")


@app.post(
url="https://api.example.com/upload",
files={"file": FILE},
)
async def upload_path(resp: Response) -> dict:
return resp.json()
```

## Supported Types

The `files` parameter accepts:

| Type | Example |
|------|---------|
| `bytes` | `b"raw data"` |
| `str` | `"text content"` |
| file object | `open("file.txt", "rb")` |
| `Path` | `Path("file.txt")` |
| tuple `(name, data)` | `("file.txt", b"data")` |
| tuple `(name, data, type)` | `("file.txt", b"data", "text/plain")` |
| dict `name -> data` | `{"file": b"data"}` |
| dict `name -> tuple` | `{"file": ("f.txt", b"data")}` |
| list of tuples | `[("f", b"a"), ("f", b"b")]` |
1 change: 1 addition & 0 deletions docs/en/tutorial/http-methods.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ async def allowed_methods(resp: Response) -> dict:
| `params` | Query parameters |
| `json` | JSON body (for POST, PUT, PATCH) |
| `data` | Raw bytes body |
| `files` | File uploads (multipart/form-data) |
| `tags` | Tags for grouping |
| `dependencies` | List of dependencies |
| `response_model` | Pydantic model for validation |
Expand Down
15 changes: 15 additions & 0 deletions docs/en/tutorial/request-parameters.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,21 @@ async def login(resp: Response) -> dict:
return resp.json()
```

## File Uploads

Use `files` to upload files as multipart/form-data:

```python
@app.post(
url="https://api.example.com/upload",
files={"file": open("photo.jpg", "rb")},
)
async def upload(resp: Response) -> dict:
return resp.json()
```

See the full [File Uploads](file-uploads.md) guide for more examples.

## Combining Parameters

You can combine multiple parameters:
Expand Down
126 changes: 126 additions & 0 deletions docs/ru/tutorial/file-uploads.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
# Загрузка файлов

FastHTTP поддерживает загрузку файлов через multipart/form-data с помощью параметра `files`.

## Простая загрузка

Передайте байты напрямую:

```python
from fasthttp import FastHTTP
from fasthttp.response import Response

app = FastHTTP()


@app.post(
url="https://api.example.com/upload",
files={"file": b"Hello, world!"},
)
async def upload(resp: Response) -> dict:
return resp.json()
```

## Загрузка с именем файла и типом контента

Передайте кортеж `(имя_файла, данные, тип_контента)`:

```python
@app.post(
url="https://api.example.com/upload",
files={"file": ("report.csv", b"name,score\nAlice,95\n", "text/csv")},
)
async def upload_csv(resp: Response) -> dict:
return resp.json()
```

## Несколько файлов

Передайте словарь с несколькими ключами:

```python
@app.post(
url="https://api.example.com/upload",
files={
"avatar": ("photo.jpg", b"\xff\xd8\xff\xe0...", "image/jpeg"),
"document": ("resume.pdf", b"%PDF-1.4...", "application/pdf"),
},
)
async def upload_multi(resp: Response) -> dict:
return resp.json()
```

Или используйте список для отправки нескольких файлов под одним именем поля:

```python
@app.post(
url="https://api.example.com/upload",
files=[
("files", ("a.txt", b"содержимое a", "text/plain")),
("files", ("b.txt", b"содержимое b", "text/plain")),
],
)
async def upload_list(resp: Response) -> dict:
return resp.json()
```

## Загрузка с JSON

Сочетайте `files` с `json` для отправки метаданных вместе с файлом:

```python
@app.post(
url="https://api.example.com/upload",
json={"title": "Моё фото", "tags": ["природа"]},
files={"file": ("sunset.jpg", b"\xff\xd8\xff\xe0...", "image/jpeg")},
)
async def upload_with_meta(resp: Response) -> dict:
return resp.json()
```

## Файловый объект

Передайте открытый файловый дескриптор:

```python
@app.post(
url="https://api.example.com/upload",
files={"file": open("photo.jpg", "rb")},
)
async def upload_file(resp: Response) -> dict:
return resp.json()
```

## Path объект

Передайте `pathlib.Path`:

```python
from pathlib import Path

FILE = Path("photo.jpg")


@app.post(
url="https://api.example.com/upload",
files={"file": FILE},
)
async def upload_path(resp: Response) -> dict:
return resp.json()
```

## Поддерживаемые типы

Параметр `files` принимает:

| Тип | Пример |
|-----|--------|
| `bytes` | `b"данные"` |
| `str` | `"текст"` |
| файловый объект | `open("file.txt", "rb")` |
| `Path` | `Path("file.txt")` |
| кортеж `(имя, данные)` | `("file.txt", b"data")` |
| кортеж `(имя, данные, тип)` | `("file.txt", b"data", "text/plain")` |
| словарь `имя -> данные` | `{"file": b"data"}` |
| словарь `имя -> кортеж` | `{"file": ("f.txt", b"data")}` |
| список кортежей | `[("f", b"a"), ("f", b"b")]` |
15 changes: 15 additions & 0 deletions docs/ru/tutorial/http-methods.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,21 @@ async def allowed_methods(resp: Response) -> dict:
return {"allow": resp.headers.get("allow", "")}
```

## Параметры декоратора

| Параметр | Описание |
|----------|----------|
| `url` | URL запроса (обязательный) |
| `params` | Query параметры |
| `json` | JSON тело (для POST, PUT, PATCH) |
| `data` | Сырые байты |
| `files` | Загрузка файлов (multipart/form-data) |
| `tags` | Теги для группировки |
| `dependencies` | Список зависимостей |
| `response_model` | Модель Pydantic для валидации |
| `request_model` | Модель Pydantic для валидации запроса |
| `responses` | Модели Pydantic для ответов с ошибками |

## Возвращаемые значения

Обработчики могут возвращать разные типы:
Expand Down
15 changes: 15 additions & 0 deletions docs/ru/tutorial/request-parameters.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,3 +84,18 @@ async def with_headers(resp: Response) -> dict:
async def slow_request(resp: Response) -> dict:
return resp.json()
```

## Загрузка файлов

Используйте `files` для загрузки файлов как multipart/form-data:

```python
@app.post(
url="https://api.example.com/upload",
files={"file": open("photo.jpg", "rb")},
)
async def upload(resp: Response) -> dict:
return resp.json()
```

Подробное руководство см. в разделе [Загрузка файлов](file-uploads.md).
Empty file added examples/files/__init__.py
Empty file.
16 changes: 16 additions & 0 deletions examples/files/simple_upload.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
from fasthttp import FastHTTP
from fasthttp.response import Response

app = FastHTTP()


@app.post(
url="https://httpbin.org/post",
files={"file": b"Hello, world!"},
)
async def upload_bytes(resp: Response) -> dict:
return resp.json()


if __name__ == "__main__":
app.run()
16 changes: 16 additions & 0 deletions examples/files/upload_file_object.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
from fasthttp import FastHTTP
from fasthttp.response import Response

app = FastHTTP()


@app.post(
url="https://httpbin.org/post",
files={"file": open(__file__, "rb")},
)
async def upload_open_file(resp: Response) -> dict:
return resp.json()


if __name__ == "__main__":
app.run()
19 changes: 19 additions & 0 deletions examples/files/upload_list.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
from fasthttp import FastHTTP
from fasthttp.response import Response

app = FastHTTP()


@app.post(
url="https://httpbin.org/post",
files=[
("files", ("a.txt", b"content of a", "text/plain")),
("files", ("b.txt", b"content of b", "text/plain")),
],
)
async def upload_list(resp: Response) -> dict:
return resp.json()


if __name__ == "__main__":
app.run()
19 changes: 19 additions & 0 deletions examples/files/upload_multiple.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
from fasthttp import FastHTTP
from fasthttp.response import Response

app = FastHTTP()


@app.post(
url="https://httpbin.org/post",
files={
"avatar": ("photo.jpg", b"\xff\xd8\xff\xe0fake-jpeg", "image/jpeg"),
"document": ("resume.pdf", b"%PDF-1.4 fake-pdf", "application/pdf"),
},
)
async def upload_multiple(resp: Response) -> dict:
return resp.json()


if __name__ == "__main__":
app.run()
Loading
Loading