Как передать файл в теле HTTP-запроса?

Ответ

Да, файлы передаются в теле HTTP-запроса. Основные методы — использование типа контента multipart/form-data для форм или application/octet-stream для бинарных данных.

1. Multipart/form-data (Стандарт для HTML-форм и API)

Используется, когда нужно отправить файлы вместе с другими полями формы.

Пример HTTP-запроса:

POST /upload HTTP/1.1
Host: example.com
Content-Type: multipart/form-data; boundary=MyBoundary123

--MyBoundary123
Content-Disposition: form-data; name="description"

Профильное фото
--MyBoundary123
Content-Disposition: form-data; name="file"; filename="avatar.jpg"
Content-Type: image/jpeg

<бинарные данные файла>
--MyBoundary123--

Пример на JavaScript с fetch:

const formData = new FormData();
formData.append('file', fileInput.files[0]);
formData.append('comment', 'Мой файл');

fetch('/api/upload', {
  method: 'POST',
  body: formData // Заголовок Content-Type установится автоматически
});

2. Direct Binary Upload

Файл передается как есть, без дополнительных полей.

Пример:

PUT /files/avatar.jpg HTTP/1.1
Host: example.com
Content-Type: application/octet-stream

<бинарные данные файла>

Ключевые моменты:

  • Для больших файлов используйте Content-Length или Transfer-Encoding: chunked.
  • Всегда проверяйте MIME-тип и размер файла на сервере в целях безопасности.

Ответ 18+ 🔞

А, ну, про передачу файлов по HTTP, да? Ну, это ж классика, блядь, каждый день этим пользуемся, а потом удивляемся, почему сервер лёг, ёпта.

Короче, есть два основных способа, как эту бинарную хуйню в сеть запихнуть.

1. Multipart/form-data (Это когда с формами возимся)

Этот способ — как раз для тех случаев, когда тебе надо не только файлик пришлёпнуть, но ещё и какую-нибудь подпись к нему прилепить, типа «смотрите, какая у меня фотка с отпуска, блядь».

Вот смотри, как запрос выглядит изнутри, страшненько:

POST /upload HTTP/1.1
Host: example.com
Content-Type: multipart/form-data; boundary=MyBoundary123

--MyBoundary123
Content-Disposition: form-data; name="description"

Профильное фото
--MyBoundary123
Content-Disposition: form-data; name="file"; filename="avatar.jpg"
Content-Type: image/jpeg

<тут прям бинарные данные, ну, нули и единички, короче>
--MyBoundary123--

Видишь эту boundary? Это типа разделитель, чтобы сервер не запутался, где у тебя описание кончается, а где файл начинается. Без него — пиздец, всё в кучу смешается.

А на фронтенде это вообще в две строки делается, ебать мои старые костыли:

const formData = new FormData();
formData.append('file', fileInput.files[0]); // Вот твой файл
formData.append('comment', 'Мой файл'); // А вот твоя подпись, типа "шедевр"

fetch('/api/upload', {
  method: 'POST',
  body: formData // И даже голову ломать не надо — браузер сам всё красиво завернёт!
});

2. Прямая загрузка бинарника (Direct Binary Upload)

А это уже для минималистов, блядь. Никаких лишних телодвижений. Берёшь файл — и пиздуй его как есть, голеньким. Часто через PUT метод.

Пример запроса:

PUT /files/avatar.jpg HTTP/1.1
Host: example.com
Content-Type: application/octet-stream

<и опять эти нули и единички, весь файл целиком>

А теперь, блядь, самое важное, чтобы потом не охуеть от последствий:

  • Размер файла: Если файл здоровый, как чёрт, обязательно указывай Content-Length, а то сервер будет ждать, пока ты всё сольёшь, или используй Transfer-Encoding: chunked — это когда файл кусочками отправляешь.
  • Безопасность, ёпта! На сервере ты ОБЯЗАН проверять две вещи, а то тебе пидары налетят:
    1. MIME-тип. Не верь тому, что в заголовке написали. Файл может называться kartinka.jpg, а внутри — скрипт на PHP, который сервер тебе ебалом вынесет. Проверяй сигнатуры, магические числа — вот это всё.
    2. Размер. Ограничивай, блядь, сразу. А то какой-нибудь умник попробует тебе терабайтный дамп базы залить, и твой сервер накроется медным тазом, в рот меня чих-пых.

Вот и вся наука. Главное — не выёбывайся и делай по уму, чтобы потом не пришлось объяснять, почему у тебя на сервере порно с котиками вместо логотипа компании лежит.