Загрузка файлов через API — это техническая задача, с которой разработчики часто сталкиваются при вызове интерфейсов для генерации AI-видео, обработки изображений и других подобных операций. В этой статье мы подробно разберем, как работает кодирование multipart/form-data, и на примере API Sora 2 (Image-to-Video) научимся мастерски загружать файлы через API.
Главная польза: после прочтения вы полностью разберетесь в низкоуровневых механизмах multipart/form-data, научитесь использовать команду curl -F для загрузки файлов и сможете самостоятельно реализовать функцию загрузки изображений для таких AI API, как Sora 2.

Основные знания о загрузке файлов через API
Прежде чем углубляться в код, нам нужно понять, почему для загрузки файлов через API требуется специальный метод кодирования.
Зачем нужен multipart/form-data
Когда вы отправляете обычные текстовые данные через API, можно использовать простое кодирование application/x-www-form-urlencoded. Однако этот метод создает серьезные проблемы при работе с файлами:
| Тип кодирования | Сценарии использования | Возможности обработки файлов | Эффективность |
|---|---|---|---|
application/x-www-form-urlencoded |
Простые пары «ключ-значение» | ❌ Не подходит | Требуется URL-экранирование для бинарных данных, низкая эффективность |
application/json |
Структурированные данные | ⚠️ Требуется Base64-кодирование | Объем увеличивается на 33% |
multipart/form-data |
Загрузка файлов | ✅ Нативная поддержка | Не требует кодирования, высокая эффективность |
multipart/form-data — это решение, предложенное в стандарте RFC 2388 в 1998 году специально для устранения проблем с одновременной отправкой текста и бинарных данных по протоколу HTTP.
Принцип работы multipart/form-data
Основная идея multipart/form-data заключается в разделении тела HTTP-запроса на несколько независимых «частей» (parts), каждая из которых может иметь свой собственный тип контента.

Подробный разбор структуры данных
Типичный запрос multipart/form-data имеет следующую структуру:
POST /v1/videos HTTP/1.1
Host: api.apiyi.com
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxk
------WebKitFormBoundary7MA4YWxk
Content-Disposition: form-data; name="prompt"
She turns around and smiles
------WebKitFormBoundary7MA4YWxk
Content-Disposition: form-data; name="model"
sora-2-pro
------WebKitFormBoundary7MA4YWxk
Content-Disposition: form-data; name="input_reference"; filename="sample.jpeg"
Content-Type: image/jpeg
[Бинарные данные изображения]
------WebKitFormBoundary7MA4YWxk--
| Компонент | Роль | Пример |
|---|---|---|
| Boundary | Уникальный идентификатор для разделения частей данных | ----WebKitFormBoundary7MA4YWxk |
| Content-Disposition | Описание метаданных этой части | form-data; name="prompt" |
| Content-Type | MIME-тип этой части | image/jpeg |
| Body | Фактическое содержимое данных | Текстовые или бинарные данные |
🎯 Технический нюанс: Boundary должен быть уникальной строкой, которая гарантированно не встретится в теле самого запроса. Сервер использует boundary для парсинга и разделения каждой части данных.
Подробный разбор команды curl -F: загрузка файлов через API на практике
curl — это, пожалуй, самый популярный консольный HTTP-клиент, а его параметр -F специально создан для отправки запросов в формате multipart/form-data.
Базовый синтаксис curl -F
curl -F "имя_поля=значение" URL
curl -F "поле_файла=@/путь/к/файлу" URL
| Формат параметра | Описание | Пример |
|---|---|---|
-F "key=value" |
Отправка обычного текстового поля | -F "prompt=Hello" |
-F "key=@file" |
Загрузка локального файла | -F "[email protected]" |
-F "key=@file;type=mime" |
Указание MIME-типа файла | -F "[email protected];type=image/jpeg" |
-F "key=@file;filename=new.jpg" |
Кастомное имя файла при загрузке | -F "[email protected];filename=upload.jpg" |
В чем разница между curl -F и другими параметрами?
Многие разработчики часто путают -F, -d и -X POST. Давайте проясним:
# ❌ ОШИБКА: -d используется для x-www-form-urlencoded, он не подходит для файлов
curl -X POST -d "[email protected]" https://api.example.com/upload
# ❌ ОШИБКА: Вручную прописан Content-Type, но используется -d
curl -X POST -H "Content-Type: multipart/form-data" -d "..." https://api.example.com/upload
# ✅ ПРАВИЛЬНО: Используйте -F, он сам установит нужный Content-Type и boundary
curl -F "[email protected]" https://api.example.com/upload
Техническая справка: При использовании
-Fcurl автоматически:
- Устанавливает метод запроса на POST.
- Прописывает заголовок
Content-Type: multipart/form-data.- Генерирует уникальный
boundary(разделитель).- Форматирует тело запроса согласно стандартам RFC.
Загрузка файлов в Sora 2 API: Практический пример
Sora 2 — это модель генерации видео от OpenAI, которая позволяет загружать референсные изображения для создания роликов. Это классический сценарий использования multipart/form-data.
Параметры API Sora 2 для генерации видео по картинке
| Параметр | Тип | Обязательно | Описание |
|---|---|---|---|
prompt |
string | ✅ | Текстовое описание видео (промпт) |
model |
string | ❌ | Выбор модели: sora-2 или sora-2-pro |
size |
string | ❌ | Разрешение: 1280x720, 720x1280, 1024x1792, 1792x1024 |
seconds |
integer | ❌ | Длительность: 4, 8, 12 секунд |
input_reference |
file | ❌ | Референсное изображение (первый кадр видео) |

Сравнение моделей Sora 2
| Характеристика | sora-2 | sora-2-pro |
|---|---|---|
| Качество генерации | Хорошее | Превосходное |
| Скорость рендеринга | Быстрая | Медленная |
| Сценарии использования | Прототипы, проверка концепций | Финальный продакшн |
| Цена | Стандартная | Высокая |
| Доступные платформы | APIYI (apiyi.com), официальный API | APIYI (apiyi.com), официальный API |
Полный пример загрузки файла в Sora 2
Вот пример использования curl для вызова Sora 2 API и создания видео на основе картинки:
curl -X POST "https://api.apiyi.com/v1/videos" \
-H "Authorization: Bearer $APIYI_KEY" \
-H "Content-Type: multipart/form-data" \
-F prompt="She turns around and smiles, then slowly walks out of the frame." \
-F model="sora-2-pro" \
-F size="1280x720" \
-F seconds="8" \
-F input_reference="@sample_720p.jpeg;type=image/jpeg"
Разбор команды
| Часть | Описание |
|---|---|
curl -X POST |
Указывает метод запроса POST |
"https://api.apiyi.com/v1/videos" |
Эндпоинт генерации видео в APIYI |
-H "Authorization: Bearer $APIYI_KEY" |
Передача API-ключа через переменную окружения |
-H "Content-Type: multipart/form-data" |
Объявление типа контента (curl -F добавит это сам) |
-F prompt="..." |
Текстовый промпт с описанием видео |
-F model="sora-2-pro" |
Выбор высококачественной модели |
-F size="1280x720" |
Горизонтальное разрешение 720p |
-F seconds="8" |
Длительность 8 секунд |
-F input_reference="@sample_720p.jpeg;type=image/jpeg" |
Загрузка референсного изображения |
🚀 Быстрый старт: Для тестирования Sora 2 API рекомендуем платформу APIYI (apiyi.com). Там всё работает «из коробки», и интеграцию можно выполнить без лишней головной боли.
На что обратить внимание при загрузке картинок
При работе с референсными изображениями в Sora 2 API учитывайте следующие моменты:
| Требование | Описание |
|---|---|
| Соответствие разрешению | Разрешение картинки должно совпадать с параметром size будущего видео |
| Поддерживаемые форматы | image/jpeg, image/png, image/webp |
| Размер файла | Рекомендуется не более 10 МБ |
| Качество картинки | Чем четче изображение и лучше композиция, тем круче будет результат |
Реализация загрузки multipart/form-data на Python
Помимо curl, в реальной разработке для загрузки файлов чаще используются языки программирования. Вот как это реализуется на Python.
Минималистичный пример
import requests
# 使用 APIYI 统一接口
url = "https://api.apiyi.com/v1/videos"
headers = {"Authorization": "Bearer YOUR_API_KEY"}
# 准备 multipart 数据
files = {
"input_reference": ("sample.jpeg", open("sample_720p.jpeg", "rb"), "image/jpeg")
}
data = {
"prompt": "She turns around and smiles, then slowly walks out of the frame.",
"model": "sora-2-pro",
"size": "1280x720",
"seconds": "8"
}
response = requests.post(url, headers=headers, data=data, files=files)
print(response.json())
Посмотреть полный код (с обработкой ошибок и опросом состояния)
import requests
import time
import os
class Sora2Client:
"""Sora 2 API 客户端 - 支持 multipart/form-data 文件上传"""
def __init__(self, api_key: str, base_url: str = "https://api.apiyi.com/v1"):
self.api_key = api_key
self.base_url = base_url
self.headers = {"Authorization": f"Bearer {api_key}"}
def create_video(
self,
prompt: str,
model: str = "sora-2",
size: str = "1280x720",
seconds: int = 8,
input_reference: str = None
) -> dict:
"""
创建视频生成任务
Args:
prompt: 视频描述
model: 模型选择 (sora-2 或 sora-2-pro)
size: 分辨率
seconds: 时长 (4, 8, 12)
input_reference: 参考图片路径 (可选)
Returns:
任务信息字典
"""
url = f"{self.base_url}/videos"
data = {
"prompt": prompt,
"model": model,
"size": size,
"seconds": str(seconds)
}
files = None
if input_reference and os.path.exists(input_reference):
# 根据文件扩展名确定 MIME 类型
ext = os.path.splitext(input_reference)[1].lower()
mime_types = {
".jpg": "image/jpeg",
".jpeg": "image/jpeg",
".png": "image/png",
".webp": "image/webp"
}
mime_type = mime_types.get(ext, "application/octet-stream")
files = {
"input_reference": (
os.path.basename(input_reference),
open(input_reference, "rb"),
mime_type
)
}
try:
response = requests.post(
url,
headers=self.headers,
data=data,
files=files,
timeout=30
)
response.raise_for_status()
return response.json()
except requests.exceptions.RequestException as e:
return {"error": str(e)}
finally:
if files and "input_reference" in files:
files["input_reference"][1].close()
def get_video_status(self, video_id: str) -> dict:
"""查询视频生成状态"""
url = f"{self.base_url}/videos/{video_id}"
response = requests.get(url, headers=self.headers, timeout=30)
return response.json()
def wait_for_completion(self, video_id: str, poll_interval: int = 10) -> dict:
"""轮询等待视频生成完成"""
while True:
status = self.get_video_status(video_id)
if status.get("status") in ["completed", "failed"]:
return status
print(f"Status: {status.get('status')}... waiting {poll_interval}s")
time.sleep(poll_interval)
# 使用示例
if __name__ == "__main__":
client = Sora2Client(api_key=os.getenv("APIYI_KEY"))
# 创建图生视频任务
result = client.create_video(
prompt="She turns around and smiles, then slowly walks out of the frame.",
model="sora-2-pro",
size="1280x720",
seconds=8,
input_reference="sample_720p.jpeg"
)
if "id" in result:
print(f"Task created: {result['id']}")
final_result = client.wait_for_completion(result["id"])
print(f"Video URL: {final_result.get('video_url')}")
else:
print(f"Error: {result}")
Совет: Получите бесплатные тестовые баллы на APIYI (apiyi.com), чтобы быстро протестировать функцию генерации видео из изображений.
Обработка multipart в библиотеке requests
Ключевые моменты при работе с multipart/form-data в библиотеке Python requests:
| Параметр | Назначение | Описание |
|---|---|---|
data |
Обычные поля формы | Формат словаря: {"key": "value"} |
files |
Поля файлов | Формат кортежа: {"name": (filename, file_obj, content_type)} |
⚠️ Внимание: При одновременном использовании параметров
dataиfiles, requests автоматически установит правильныйContent-Typeи boundary, указывать их вручную не нужно.
Реализация на JavaScript/Node.js
Браузерная среда (FormData API)
const formData = new FormData();
formData.append('prompt', 'She turns around and smiles');
formData.append('model', 'sora-2-pro');
formData.append('size', '1280x720');
formData.append('seconds', '8');
formData.append('input_reference', fileInput.files[0]);
fetch('https://api.apiyi.com/v1/videos', {
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_API_KEY'
// 注意: 不要手动设置 Content-Type
},
body: formData
})
.then(response => response.json())
.then(data => console.log(data));
Среда Node.js
const FormData = require('form-data');
const fs = require('fs');
const axios = require('axios');
const form = new FormData();
form.append('prompt', 'She turns around and smiles');
form.append('model', 'sora-2-pro');
form.append('size', '1280x720');
form.append('seconds', '8');
form.append('input_reference', fs.createReadStream('sample_720p.jpeg'), {
contentType: 'image/jpeg'
});
axios.post('https://api.apiyi.com/v1/videos', form, {
headers: {
...form.getHeaders(),
'Authorization': 'Bearer YOUR_API_KEY'
}
})
.then(response => console.log(response.data));
💡 Важный совет: При использовании
FormDataв браузере не нужно вручную устанавливать заголовокContent-Type. Браузер автоматически добавит корректный параметр boundary.
Устранение распространенных проблем с multipart/form-data
Основные причины неудачной загрузки
| Проблема | Симптомы | Решение |
|---|---|---|
| Отсутствие boundary | Сервер возвращает 400 | Не устанавливайте Content-Type вручную, позвольте инструменту сгенерировать его автоматически |
| Ошибка типа MIME | Файл отклонен | Явно укажите тип с помощью ;type=image/jpeg |
| Ошибка пути к файлу | Файл не найден | Убедитесь, что путь после символа @ указан верно; поддерживаются как относительные, так и абсолютные пути |
| Несоответствие разрешения | Ошибка Sora API | Разрешение изображения должно строго совпадать с параметром size |
| Файл слишком большой | Таймаут или отказ | Сожмите изображение или используйте загрузку по частям (чанками) |
Советы по отладке
Используйте флаг -v в curl, чтобы просмотреть детали запроса:
curl -v -F "[email protected]" https://api.example.com/upload
Это покажет:
- Заголовки запроса (включая автоматически сгенерированный Content-Type и boundary)
- Структуру тела запроса
- Ответ сервера
Часто задаваемые вопросы
Q1: Что лучше: multipart/form-data или кодирование в Base64?
Для загрузки файлов multipart/form-data подходит гораздо лучше. Base64 увеличивает объем данных примерно на 33%, что создает лишнюю нагрузку на сеть и замедляет обработку на стороне сервера. Multipart передает бинарные данные напрямую, поэтому он эффективнее.
Однако в некоторых случаях (например, при работе с WebSocket или API, принимающими только JSON), Base64 может быть единственным вариантом. При работе через платформу APIYI apiyi.com мы рекомендуем отдавать приоритет multipart/form-data для лучшей производительности.
Q2: Почему мой запрос curl -F завершается ошибкой?
Самые частые причины:
- Проблемы с путем: Убедитесь, что после символа
@идет корректный путь к файлу. - Права доступа: Проверьте, есть ли у системы права на чтение этого файла.
- Тип MIME: Некоторые API требуют обязательного указания правильного content-type.
Советуем сначала протестировать запрос в среде APIYI apiyi.com — там можно получить подробную информацию об ошибках и быстро понять, что пошло не так.
Q3: Какие форматы изображений поддерживает Sora 2 API?
Для параметра input_reference в Sora 2 API поддерживаются следующие форматы:
- JPEG (
.jpg,.jpeg) — рекомендуемый вариант, хорошее сжатие. - PNG (
.png) — если нужна прозрачность. - WebP (
.webp) — современный формат с небольшим весом.
Разрешение изображения должно соответствовать параметру size целевого видео. Например, если вы создаете видео 1280x720, референсное изображение тоже должно быть 1280x720.
Q4: Как лучше всего загружать большие файлы?
Если файл весит много, попробуйте следующее:
- Загрузка по частям (Chunking): разбейте файл на небольшие блоки и отправляйте их по очереди.
- Оптимизация: сожмите файл перед отправкой, если это не критично для качества.
- Дозагрузка: используйте механизмы, позволяющие продолжить загрузку с места обрыва.
Кстати, multipart/form-data поддерживает потоковую передачу — сервер может начать обработку данных, не дожидаясь окончания загрузки всего файла, что отлично подходит для больших объектов.
Итоги
В этой статье мы подробно разобрали ключевую технологию загрузки файлов через API — multipart/form-data:
Вспомним основные моменты:
| Ключевой момент | Описание |
|---|---|
| Принцип кодирования | Разделитель boundary разбивает данные на части, у каждой из которых свой Content-Type |
Команда curl -F |
-F "key=value" для отправки текста, -F "key=@file" для загрузки файла |
| Практика с Sora 2 | Параметр input_reference для загрузки референсных изображений (разрешение должно совпадать) |
| Реализация на разных языках | Python requests / JavaScript FormData |
| Советы по отладке | Используйте curl -v для просмотра полного лога запроса |
Понимание того, как работает multipart/form-data, — это базовый навык для разработки с использованием AI API. Будь то генерация видео в Sora 2, компьютерное зрение в GPT-4 Vision или любые другие интерфейсы, требующие передачи файлов, — фундаментальные принципы везде одинаковы.
Рекомендуем использовать APIYI (apiyi.com) для быстрой проверки функций загрузки файлов. Попробуйте унифицированный API и воспользуйтесь подробной технической поддержкой.
Автор: Команда APIYI | Делимся технологиями API больших языковых моделей
Техническое сообщество: Посетите apiyi.com для получения дополнительных ресурсов по разработке
Справочные материалы
-
RFC 2388: Спецификация стандарта
multipart/form-data- Ссылка:
tools.ietf.org/html/rfc2388
- Ссылка:
-
Документация curl: Multipart Formposts
- Ссылка:
everything.curl.dev/http/post/multipart
- Ссылка:
-
MDN Web Docs: Использование объектов FormData
- Ссылка:
developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest_API/Using_FormData_Objects
- Ссылка:
-
Документация OpenAI Sora API: Руководство по генерации видео
- Ссылка:
platform.openai.com/docs/guides/video-generation
- Ссылка:
