|

إتقان تحميل الملفات عبر API: الدليل الشامل لـ multipart/form-data مع أمثلة عملية لـ Sora 2

يعد رفع ملفات واجهة برمجة التطبيقات (API) مطلبًا تقنيًا شائعًا يواجهه المطورون عند استدعاء واجهات برمجة تطبيقات الذكاء الاصطناعي لإنشاء الفيديو، ومعالجة الصور، وما إلى ذلك. سيتناول هذا المقال شرحًا منهجيًا لمبدأ عمل طريقة الترميز multipart/form-data، وسنأخذ واجهة برمجة تطبيقات Sora 2 (تحويل الصورة إلى فيديو) كمثال، لمساعدتك في إتقان المهارات الأساسية لرفع ملفات API.

القيمة الجوهرية: بعد قراءة هذا المقال، ستفهم تمامًا الآلية الأساسية لـ multipart/form-data، وستتعلم كيفية استخدام أمر curl -F لرفع الملفات، وستتمكن من تنفيذ ميزة رفع الصور لواجهات AI API مثل Sora 2 بشكل مستقل.

api-file-upload-multipart-form-data-guide-ar 图示


المعرفة الأساسية لرفع الملفات عبر 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) مستقلة، حيث يمكن لكل جزء أن يكون له نوع محتوى خاص به.

api-file-upload-multipart-form-data-guide-ar 图示

شرح مفصل لبنية البيانات

يحتوي طلب 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 تلقائياً بـ:

  1. ضبط طريقة الطلب (Method) لتكون POST.
  2. ضبط الرأس Content-Type: multipart/form-data.
  3. توليد boundary فريد.
  4. تنسيق جسم الطلب (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 الصورة المرجعية، تُستخدم كإطار أول للفيديو

api-file-upload-multipart-form-data-guide-ar 图示

مقارنة بين نماذج 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؟

تشمل الأسباب الشائعة ما يلي:

  1. مشكلة في مسار الملف: تأكد من وضع مسار الملف الصحيح بعد علامة @.
  2. مشكلة في الصلاحيات: تحقق من صلاحيات قراءة الملف.
  3. نوع 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: كيف يمكن التعامل مع رفع الملفات الكبيرة؟

بالنسبة لرفع الملفات الكبيرة، يمكنك التفكير في:

  1. الرفع المجزأ (Chunked Upload): تقسيم الملف إلى أجزاء صغيرة ورفعها بالتتابع.
  2. تحسين الضغط: ضغط الملف مع الحفاظ على الجودة.
  3. استئناف الرفع (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.

المصادر والمراجع

  1. RFC 2388: معيار multipart/form-data

    • الرابط: tools.ietf.org/html/rfc2388
  2. وثائق curl الرسمية: منشورات النماذج متعددة الأجزاء (Multipart Formposts)

    • الرابط: everything.curl.dev/http/post/multipart
  3. وثائق MDN Web: استخدام كائنات FormData

    • الرابط: developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest_API/Using_FormData_Objects
  4. وثائق OpenAI Sora API: دليل توليد الفيديو (Video Generation Guide)

    • الرابط: platform.openai.com/docs/guides/video-generation

موضوعات ذات صلة