يعد رفع ملفات واجهة برمجة التطبيقات (API) مطلبًا تقنيًا شائعًا يواجهه المطورون عند استدعاء واجهات برمجة تطبيقات الذكاء الاصطناعي لإنشاء الفيديو، ومعالجة الصور، وما إلى ذلك. سيتناول هذا المقال شرحًا منهجيًا لمبدأ عمل طريقة الترميز multipart/form-data، وسنأخذ واجهة برمجة تطبيقات Sora 2 (تحويل الصورة إلى فيديو) كمثال، لمساعدتك في إتقان المهارات الأساسية لرفع ملفات 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 هي أداة سطر الأوامر الأكثر استخداماً كعميل 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
توضيح تقني: عند استخدام
-Fيقوم curl تلقائياً بـ:
- ضبط طريقة الطلب (Method) لتكون POST.
- ضبط الرأس
Content-Type: multipart/form-data.- توليد
boundaryفريد.- تنسيق جسم الطلب (Request Body) وفقاً لمعايير RFC.
تطبيق عملي: رفع الملفات عبر Sora 2 API
Sora 2 هو نموذج توليد الفيديو الذي أطلقته OpenAI، ويدعم رفع صور مرجعية عبر API لتوليد الفيديو. هذا تطبيق نموذجي لاستخدام multipart/form-data.
معلمات Sora 2 API لتحويل الصور إلى فيديو
| المعلمة | النوع | مطلوبة | الشرح |
|---|---|---|---|
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" |
نقطة نهاية توليد فيديو Sora 2 في 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" |
رفع الصورة المرجعية |
🚀 ابدأ بسرعة: نوصي باستخدام منصة APIYI apiyi.com لاختبار Sora 2 API بسرعة. توفر هذه المنصة واجهات جاهزة للاستخدام، مما يسمح بإتمام التكامل دون الحاجة إلى إعدادات معقدة.
ملاحظات حول رفع الصور
عند استخدام Sora 2 API لرفع صور مرجعية، يرجى مراعاة ما يلي:
| المتطلبات | الشرح |
|---|---|
| مطابقة الدقة | يجب أن تتطابق دقة الصورة مع معلمة الدقة (size) المحددة للفيديو |
| التنسيقات المدعومة | image/jpeg, image/png, image/webp |
| حجم الملف | يُنصح بألا يتجاوز 10 ميجابايت |
| جودة الصورة | الصور الواضحة ذات التكوين المكتمل تعطي نتائج أفضل |
تنفيذ رفع البيانات بصيغة multipart/form-data باستخدام بايثون
إلى جانب curl، يشيع استخدام لغات البرمجة في التطوير العملي لرفع الملفات. إليك كيفية تنفيذ ذلك باستخدام بايثون.
مثال مبسط للغاية
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 باستخدام مكتبة requests في بايثون:
| المعامل | الغرض | التوضيح |
|---|---|---|
data |
حقول النموذج العادية | تنسيق القاموس: {"key": "value"} |
files |
حقول الملفات | تنسيق Tuple: {"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 للتحديد بشكل صريح |
| خطأ في مسار الملف | تعذر العثور على الملف | تأكد من صحة المسار بعد علامة @؛ المسارات النسبية والمطلقة مدعومة |
| عدم تطابق الدقة (Resolution) | خطأ من واجهة برمجة تطبيقات Sora | يجب أن تتطابق دقة الصورة مع بارامتر الحجم (size) |
| الملف كبير جدًا | مهلة زمنية (Timeout) أو رفض الطلب | قم بضغط الصورة أو استخدم الرفع المجزأ (Chunked upload) |
نصائح لتصحيح الأخطاء (Debugging)
استخدم الخيار -v في أداة curl لعرض الطلب كاملاً:
curl -v -F "[email protected]" https://api.example.com/upload
سيعرض لك هذا:
- ترويسات الطلب (بما في ذلك الـ Content-Type المولد تلقائيًا والـ boundary)
- هيكل جسم الطلب (Request body)
- استجابة الخادم
الأسئلة الشائعة
س1: أيهما أفضل، multipart/form-data أم ترميز Base64؟
تنسيق multipart/form-data هو الأنسب لرفع الملفات. يزيد ترميز Base64 من حجم الملف بنسبة 33% تقريبًا، مما يطيل وقت النقل عبر الشبكة ويزيد العبء على الخادم. أما multipart/form-data فينقل البيانات الثنائية (Binary) مباشرة، وهو أكثر كفاءة.
ومع ذلك، في بعض الحالات (مثل WebSocket أو واجهات JSON ذات الحقل الواحد)، قد يكون Base64 هو الخيار الوحيد. عند استدعاء واجهات البرمجة عبر منصة APIYI (apiyi.com)، يُفضل استخدام multipart/form-data للحصول على أداء أفضل.
س2: لماذا يفشل الرفع لدي باستخدام curl -F؟
تشمل الأسباب الشائعة ما يلي:
- مشكلة في مسار الملف: تأكد من وضع مسار الملف الصحيح بعد علامة
@. - مشكلة في الصلاحيات: تحقق من صلاحيات قراءة الملف.
- نوع MIME: تتطلب بعض واجهات البرمجة تحديد content-type بشكل صحيح.
نقترح عليك أولاً استخدام بيئة الاختبار في APIYI (apiyi.com) للتحقق من تنسيق الطلب؛ حيث توفر المنصة معلومات خطأ تفصيلية تساعدك في تحديد المشكلة بسرعة.
س3: ما هي تنسيقات الصور التي تدعمها واجهة برمجة تطبيقات Sora 2؟
تدعم واجهة Sora 2 التنسيقات التالية للصور المستخدمة في input_reference:
- JPEG (
.jpg,.jpeg) – موصى به، نسبة ضغط جيدة. - PNG (
.png) – يدعم القنوات الشفافة. - WebP (
.webp) – تنسيق حديث، حجم صغير.
يجب أن تتطابق دقة الصورة مع بارامتر الحجم (size) للفيديو المستهدف. على سبيل المثال، إذا كنت تستخدم دقة 1280x720 للفيديو، فيجب أن تكون الصورة المرجعية بدقة 1280×720 أيضًا.
س4: كيف يمكن التعامل مع رفع الملفات الكبيرة؟
بالنسبة لرفع الملفات الكبيرة، يمكنك التفكير في:
- الرفع المجزأ (Chunked Upload): تقسيم الملف إلى أجزاء صغيرة ورفعها بالتتابع.
- تحسين الضغط: ضغط الملف مع الحفاظ على الجودة.
- استئناف الرفع (Resumable Upload): دعم إكمال الرفع من نقطة التوقف في حال فشله.
يدعم تنسيق multipart/form-data النقل المتدفق (Streaming)، حيث يمكن للخادم المعالجة أثناء الاستلام، مما يجعله مناسبًا لسيناريوهات الملفات الضخمة.
ملخص
يتناول هذا المقال بالتفصيل التقنية الأساسية لرفع الملفات عبر واجهة برمجة التطبيقات (API)، وهي multipart/form-data:
مراجعة لأبرز النقاط التقنية:
| النقطة | التوضيح |
|---|---|
| مبدأ الترميز | استخدام حدود (boundary) للفصل بين البيانات المتعددة، مع تحديد Content-Type مستقل لكل جزء. |
أمر curl -F |
استخدام -F "key=value" لإرسال النصوص، و -F "key=@file" لرفع الملفات. |
| تطبيق عملي مع Sora 2 | استخدام معامل input_reference لرفع الصور المرجعية، مع ضرورة تطابق الدقة (resolution). |
| التنفيذ بلغات برمجة مختلفة | مكتبة requests في بايثون أو FormData في جافا سكريبت. |
| مهارات تصحيح الأخطاء (Debugging) | استخدام curl -v لعرض تفاصيل الطلب (Request) بالكامل. |
يُعد إتقان multipart/form-data مهارة أساسية في تطوير تطبيقات نماذج اللغة الكبيرة (AI API). وسواء كنت تعمل على توليد الفيديو باستخدام Sora 2، أو فهم الصور عبر GPT-4 Vision، أو أي واجهة برمجة تطبيقات أخرى تتطلب رفع ملفات، فإن المبادئ الأساسية تظل واحدة.
نوصي باستخدام APIYI (apiyi.com) للتحقق من ميزة رفع الملفات بسرعة، حيث يمكنك تجربة واجهة برمجة تطبيقات موحدة والحصول على دعم تقني شامل.
المؤلف: فريق APIYI | متخصصون في مشاركة تقنيات نماذج اللغة الكبيرة (AI APIs)
التواصل التقني: قم بزيارة apiyi.com للحصول على المزيد من موارد تطوير الـ APIs.
المصادر والمراجع
-
RFC 2388: معيار
multipart/form-data- الرابط:
tools.ietf.org/html/rfc2388
- الرابط:
-
وثائق curl الرسمية: منشورات النماذج متعددة الأجزاء (Multipart Formposts)
- الرابط:
everything.curl.dev/http/post/multipart
- الرابط:
-
وثائق MDN Web: استخدام كائنات
FormData- الرابط:
developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest_API/Using_FormData_Objects
- الرابط:
-
وثائق OpenAI Sora API: دليل توليد الفيديو (Video Generation Guide)
- الرابط:
platform.openai.com/docs/guides/video-generation
- الرابط:
