Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Можно ли передать файл через HTTP?
Да, абсолютно возможно. HTTP полностью поддерживает передачу файлов. Нужно просто выбрать правильный метод и формат.
Два сценария передачи файла
1. Upload — клиент отправляет файл на сервер (POST)
Пользователь загружает аватар, документ, видео. Клиент отправляет файл в теле запроса.
POST /api/v1/users/123/avatar
Content-Type: multipart/form-data
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="file"; filename="photo.jpg"
Content-Type: image/jpeg
[бинарные данные файла]
------WebKitFormBoundary7MA4YWxkTrZu0gW--
2. Download — сервер отправляет файл клиенту (GET)
Пользователь скачивает отчёт, счёт, экспорт. Сервер отправляет файл в ответе.
GET /api/v1/reports/123/download
Ответ:
Content-Type: application/pdf
Content-Disposition: attachment; filename="report.pdf"
Content-Length: 524288
[бинарные данные PDF]
Upload файла — детали
Формат multipart/form-data
Это стандартный формат для загрузки файлов (то же, что используется при отправке формы в браузере).
POST /api/v1/documents
Content-Type: multipart/form-data; boundary=----FormBoundary
------FormBoundary
Content-Disposition: form-data; name="file"; filename="contract.pdf"
Content-Type: application/pdf
[бинарные данные PDF]
------FormBoundary
Content-Disposition: form-data; name="title"
Квартальный отчёт
------FormBoundary--
Особенности
- Можно загружать несколько файлов за раз (разные части)
- Можно добавлять дополнительные поля (название, описание)
- Content-Type автоматически определяется по расширению файла
Практический пример (Python + FastAPI)
from fastapi import UploadFile, File
@app.post("/api/v1/documents")
async def upload_document(file: UploadFile = File(...)):
# Сохранить файл
with open(f"uploads/{file.filename}", "wb") as buffer:
contents = await file.read()
buffer.write(contents)
return {"filename": file.filename, "size": len(contents)}
Download файла — детали
Заголовки для скачивания
HTTP/1.1 200 OK
Content-Type: application/pdf
Content-Disposition: attachment; filename="report.pdf"
Content-Length: 1048576
Cache-Control: no-cache
[бинарные данные файла]
Content-Disposition
attachment— браузер скачает файл (не откроет в новой вкладке)inline— браузер попытается открить файл (для PDF, изображений)filename="name.pdf"— подсказка имени файла
Content-Type
application/pdf— PDF документapplication/vnd.ms-excel— Excelimage/png— изображениеtext/csv— CSV данныеapplication/octet-stream— бинарный файл (неизвестный тип)
Практический пример (Python + FastAPI)
from fastapi.responses import FileResponse
@app.get("/api/v1/reports/{report_id}/download")
async def download_report(report_id: str):
file_path = f"reports/{report_id}.pdf"
return FileResponse(
path=file_path,
filename="report.pdf",
media_type="application/pdf"
)
Ограничения и требования
Размер файла
HTTP нет встроенного ограничения, но на практике есть:
- Браузеры обычно поддерживают до 2-4 GB (зависит от памяти)
- Веб-серверы (Nginx, Apache) ограничивают
client_max_body_size(по умолчанию 1-10 MB) - CDN часто ограничивают до 100 MB
# Nginx конфиг
client_max_body_size 100M; # Разрешить загружать файлы до 100 MB
Timeout
Для больших файлов нужно увеличить timeout (иначе соединение разорвётся):
GET /api/v1/large-export/download
Timeout: 300s # 5 минут
Best Practices
1. Валидация на сервере
ALLOWED_EXTENSIONS = {'pdf', 'docx', 'xlsx'}
MAX_FILE_SIZE = 10 * 1024 * 1024 # 10 MB
async def upload_document(file: UploadFile = File(...)):
# Проверить расширение
if not file.filename.endswith(tuple(ALLOWED_EXTENSIONS)):
raise HTTPException(status_code=400, detail="Invalid file type")
# Проверить размер
contents = await file.read()
if len(contents) > MAX_FILE_SIZE:
raise HTTPException(status_code=413, detail="File too large")
# Сохранить
...
2. Сканирование на вирусы
Для production всегда проверяй загруженные файлы (ClamAV, VirusTotal API).
3. Безопасное хранение
- Не сохраняй в веб-корне (public/)
- Используй случайные имена (
uuid4().hex + extension) - Храни метаданные в БД (кто загрузил, когда, оригинальное имя)
4. S3/облако для больших файлов
Для high-load систем:
- Не сохраняй файлы на сервере
- Используй AWS S3, Google Cloud Storage, Yandex.Cloud
- Сервер возвращает подписанный URL для скачивания
# Генерируем signed URL для скачивания из S3
presigned_url = s3_client.generate_presigned_url(
'get_object',
Params={'Bucket': 'my-bucket', 'Key': 'reports/report-123.pdf'},
ExpiresIn=3600 # Ссылка действительна 1 час
)
return {"download_url": presigned_url}
5. Прогресс загрузки
Для больших файлов покажи прогресс-бар:
const xhr = new XMLHttpRequest();
xhr.upload.addEventListener('progress', (e) => {
const percentComplete = (e.loaded / e.total) * 100;
console.log(`Uploaded: ${percentComplete}%`);
});
xhr.open('POST', '/api/v1/documents', true);
xhr.send(formData);
Вывод
ХТТП полностью поддерживает файлы:
- Upload: POST с
multipart/form-data - Download: GET с
Content-Disposition: attachment
Для production обязательно:
- Валидировать файлы (расширение, размер)
- Сканировать на вирусы
- Использовать облачное хранилище (S3) для масштабируемости
- Защищать от DoS (ограничивать размер, timeout)