← Назад к вопросам
Как выглядит POST запрос передачи файла?
1.0 Junior🔥 221 комментариев
#REST API и HTTP
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
POST запрос передачи файла
POST запрос для передачи файлов использует специальный формат multipart/form-data, который позволяет передавать бинарные данные вместе с другой информацией на сервер.
Структура multipart/form-data запроса
Сырой HTTP запрос
POST /upload HTTP/1.1
Host: api.example.com
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary
Content-Length: 1024
------WebKitFormBoundary
Content-Disposition: form-data; name="file"; filename="photo.jpg"
Content-Type: image/jpeg
[бинарные данные файла...]
------WebKitFormBoundary
Content-Disposition: form-data; name="description"
My photo
------WebKitFormBoundary--
Компоненты запроса
- Content-Type: multipart/form-data — указывает тип контента
- boundary — разделитель между частями данных
- Content-Disposition — описание каждого поля
- Content-Type (для файла) — тип файла (MIME type)
- Бинарные данные — содержимое файла
Отправка файла с Python (requests)
Простой вариант: один файл
import requests
with open("photo.jpg", "rb") as f:
files = {"file": f}
response = requests.post("https://api.example.com/upload", files=files)
print(response.json())
Расширенный вариант: файл + дополнительные данные
import requests
from pathlib import Path
file_path = Path("photo.jpg")
# Способ 1: открыть файл вручную
with open(file_path, "rb") as f:
files = {"file": ("photo.jpg", f, "image/jpeg")}
data = {"description": "My photo", "user_id": 123}
response = requests.post(
"https://api.example.com/upload",
files=files,
data=data
)
print(response.json())
# Способ 2: автоматическое определение типа
response = requests.post(
"https://api.example.com/upload",
files={"file": open(file_path, "rb")},
data={"description": "My photo"}
)
Несколько файлов одновременно
import requests
from pathlib import Path
# Несколько файлов одного поля
files = {
"files": [
("photo1.jpg", open("photo1.jpg", "rb"), "image/jpeg"),
("photo2.jpg", open("photo2.jpg", "rb"), "image/jpeg"),
("photo3.jpg", open("photo3.jpg", "rb"), "image/jpeg"),
]
}
response = requests.post(
"https://api.example.com/upload-multiple",
files=files
)
Отправка файла с использованием httpx (асинхронный вариант)
import httpx
import asyncio
async def upload_file():
async with httpx.AsyncClient() as client:
with open("photo.jpg", "rb") as f:
files = {"file": ("photo.jpg", f, "image/jpeg")}
response = await client.post(
"https://api.example.com/upload",
files=files
)
return response.json()
result = asyncio.run(upload_file())
print(result)
Обработка на стороне FastAPI сервера
Получение одного файла
from fastapi import FastAPI, File, UploadFile
from fastapi.responses import JSONResponse
app = FastAPI()
@app.post("/upload")
async def upload_file(file: UploadFile = File(...)):
# UploadFile автоматически распаковывает multipart данные
contents = await file.read()
# Сохранение файла
with open(f"uploads/{file.filename}", "wb") as f:
f.write(contents)
return {
"filename": file.filename,
"content_type": file.content_type,
"size": len(contents)
}
Получение нескольких файлов
from fastapi import FastAPI, File, UploadFile
from typing import List
@app.post("/upload-multiple")
async def upload_multiple(files: List[UploadFile] = File(...)):
results = []
for file in files:
contents = await file.read()
results.append({
"filename": file.filename,
"size": len(contents),
"content_type": file.content_type
})
return {"uploaded": results}
Файл + дополнительные данные
from fastapi import FastAPI, File, UploadFile, Form
from pydantic import BaseModel
@app.post("/upload-with-metadata")
async def upload_with_metadata(
file: UploadFile = File(...),
description: str = Form(...),
user_id: int = Form(...)
):
contents = await file.read()
return {
"filename": file.filename,
"description": description,
"user_id": user_id,
"size": len(contents)
}
Детальный класс для работы с файлами
from pathlib import Path
from typing import Optional, List
import requests
import mimetypes
class FileUploader:
def __init__(self, api_url: str):
self.api_url = api_url
def upload_single(
self,
file_path: str,
metadata: Optional[dict] = None
) -> dict:
"""Загрузить один файл"""
path = Path(file_path)
if not path.exists():
raise FileNotFoundError(f"File not found: {file_path}")
mime_type, _ = mimetypes.guess_type(file_path)
with open(file_path, "rb") as f:
files = {"file": (path.name, f, mime_type)}
response = requests.post(
f"{self.api_url}/upload",
files=files,
data=metadata or {}
)
return response.json()
def upload_multiple(
self,
file_paths: List[str],
metadata: Optional[dict] = None
) -> dict:
"""Загрузить несколько файлов"""
files = []
for file_path in file_paths:
path = Path(file_path)
mime_type, _ = mimetypes.guess_type(file_path)
with open(file_path, "rb") as f:
files.append((
"files",
(path.name, f.read(), mime_type)
))
response = requests.post(
f"{self.api_url}/upload-multiple",
files=files,
data=metadata or {}
)
return response.json()
def upload_with_validation(
self,
file_path: str,
allowed_types: List[str],
max_size_mb: int = 10
) -> dict:
"""Загрузить файл с проверкой"""
path = Path(file_path)
# Проверка существования
if not path.exists():
raise FileNotFoundError(f"File not found: {file_path}")
# Проверка размера
size_mb = path.stat().st_size / (1024 * 1024)
if size_mb > max_size_mb:
raise ValueError(f"File too large: {size_mb}MB > {max_size_mb}MB")
# Проверка типа
mime_type, _ = mimetypes.guess_type(file_path)
if mime_type not in allowed_types:
raise ValueError(f"Invalid file type: {mime_type}")
with open(file_path, "rb") as f:
files = {"file": (path.name, f, mime_type)}
response = requests.post(
f"{self.api_url}/upload",
files=files
)
return response.json()
# Использование
uploader = FileUploader("https://api.example.com")
# Простая загрузка
result = uploader.upload_single(
"photo.jpg",
metadata={"description": "My photo"}
)
# Загрузка с проверкой
result = uploader.upload_with_validation(
"document.pdf",
allowed_types=["application/pdf"],
max_size_mb=50
)
Практические примеры MIME типов
# Изображения
"image/jpeg" # .jpg, .jpeg
"image/png" # .png
"image/gif" # .gif
"image/webp" # .webp
# Документы
"application/pdf" # .pdf
"application/msword" # .doc
"application/vnd.openxmlformats-officedocument.wordprocessingml.document" # .docx
"text/plain" # .txt
# Архивы
"application/zip" # .zip
"application/x-rar-compressed" # .rar
"application/gzip" # .gz
# Видео
"video/mp4" # .mp4
"video/mpeg" # .mpeg
"video/quicktime" # .mov
Отправка больших файлов (streaming)
import requests
def upload_large_file(file_path: str, chunk_size: int = 1024 * 1024):
"""Загрузить большой файл по частям"""
with open(file_path, "rb") as f:
# requests автоматически stream-ит файлы
response = requests.post(
"https://api.example.com/upload",
data=f # Передаёшь file object напрямую
)
return response.json()
# Или явно с headers
with open("large_file.zip", "rb") as f:
response = requests.post(
"https://api.example.com/upload",
data=f,
headers={"Content-Type": "application/octet-stream"}
)
Заключение
POST запрос для файлов использует формат multipart/form-data:
- Content-Type: multipart/form-data с boundary разделителем
- Каждая часть имеет Content-Disposition и Content-Type
- Python requests автоматически форматирует multipart запрос
- FastAPI/Starlette автоматически парсят файлы через UploadFile
- Всегда проверяй размер, тип и источник файла