← Назад к вопросам

Можно ли передать файл через HTTP?

1.0 Junior🔥 151 комментариев
#Интеграции и API

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI26 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Можно ли передать файл через 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 — Excel
  • image/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)