طلب POST ، محتوى مركب (متعدد الأجزاء / بيانات النموذج)

متعدد الأجزاء / نموذج البيانات


نشر البيانات المركبة



في حياة أي مبرمج ، تظهر المشاكل التي تصادف الشخص. لا أحب الحل القياسي وهذا كل شيء! وأحيانًا يحدث أن الحلول القياسية لا تعمل لسبب ما. يتخطى بعض الأشخاص مثل هذه المهام ، بينما يحب البعض الآخر حلها. يمكنك حتى القول إنهم وجدواهم بأنفسهم. تتمثل إحدى هذه المهام في إرسال ملف أو عدة ملفات باستخدام طريقة POST.



من المحتمل أن يقول البعض أن هذه المهمة ليست مهمة على الإطلاق. بعد كل شيء ، هناك مكتبة CURL رائعة بسيطة للغاية وتحل هذه المشكلة بسهولة! لكن لا تستعجل. نعم ، CURL مكتبة قوية ، نعم ، تقوم بتحميل الملفات ، ولكن ... كما تعلم ، تحتوي على ميزة صغيرة - يجب وضع الملف على محرك الأقراص الثابتة لديك!



الآن دعنا نتخيل الموقف التالي ، فأنت تقوم بإنشاء ملف ديناميكيًا أو أنه موجود بالفعل في الذاكرة وتحتاج إلى إرساله باستخدام طريقة POST إلى خادم ويب بعيد. ما يحدث بعد ذلك؟ هل تحتاج إلى حفظه قبل إرساله؟ هذا بالضبط ما سيفعله 90٪ من المبرمجين. لماذا نبحث عن المشاكل غير الضرورية إذا كان الحل يكمن في السطح؟ لكننا لسنا معكم من هؤلاء الـ 90٪! نحن أفضل ، يمكننا حل أي مشكلة. لماذا نحتاج إلى إجراء إضافي؟ أولاً ، يستخدم نظام الملفات غير السريع لمحرك الأقراص الثابتة. ثانيًا ، قد لا نتمكن من الوصول إلى نظام الملفات ، أو يتم تخصيص مساحة صغيرة جدًا هناك.



كيف يمكننا بعد ذلك حل هذه المشكلة؟ للقيام بذلك ، تحتاج إلى النظر في كيفية نقل البيانات فعليًا بطريقة POST. الحل الوحيد هو نقل الملف كطلب مركب باستخداممتعدد الأجزاء / نموذج البيانات . تم توثيق هذه التقنية جيدًا في RFC7578 . دعنا نلقي نظرة على الشكل الذي سيبدو عليه جسم طلب POST متعدد الأجزاء / بيانات النموذج:

POST /form.html HTTP / 1.1
المضيف: server.com
المرجع: http://server.com/form.html
وكيل المستخدم: Mozilla
نوع المحتوى: متعدد الأجزاء / بيانات النموذج ؛ الحدود = ------------- 573cf973d5228
طول المحتوى: 288
الاتصال: البقاء على قيد الحياة
ابق على قيد الحياة: 300
(سطر فارغ)
(الديباجة مفقودة)
--------------- 573cf973d5228
ترتيب المحتوى: نموذج البيانات ؛ الاسم = "الحقل"

نص
--------------- 573cf973d5228
ترتيب المحتوى: نموذج البيانات ؛ الاسم = "ملف" ؛ اسم الملف = "sample.txt"
نوع المحتوى: نص / عادي

ملف المحتوى
--------------- 573cf973d5228--






يتكون جسمنا من جزأين ، في الجزء الأول نقوم بتمرير قيمة اسم حقل النموذج = "الحقل" يساوي: نص . في الجزء الثاني ، نقوم بتمرير اسم الحقل = "file" بمحتوى اسم الملف = "sample.txt": ملف المحتوى . في العنوان ، نحدد تنسيق محتوى طلب POST - نوع المحتوى: متعدد الأجزاء / بيانات النموذج ، وسلسلة الأجزاء الفاصلة : الحدود = ------------- 573cf973d5228 وطول الرسالة - طول المحتوى: 288 .



يبقى ، في الواقع ، كتابة برنامج يطبق هذه الطريقة. نظرًا لأننا أشخاص أذكياء ولا نكتب نفس الشيء مائة مرة في مشاريع مختلفة ، فسنرتب كل شيء في شكل فئة تنفذ هذه الطريقة. بالإضافة إلى ذلك ، دعنا نوسعها لخيارات مختلفة لإرسال كل من الملفات وعناصر النموذج البسيطة. ولتمييز وجود ملف بين مصفوفة بيانات POST ، فلنقم بإنشاء ملف منفصل - حاوية تحتوي على محتويات الملف وبياناته (الاسم والامتداد). وبالتالي ، سيبدو كما يلي:



<pre>
class oFile
{
 private $name;
 private $mime;
 private $content;

 public function __construct($name, $mime=null, $content=null)
 {
// ,  $content=null,    $name -   
  if(is_null($content))
  {
//     (,    )
   $info = pathinfo($name);
//            
   if(!empty($info['basename']) && is_readable($name))
    {
     $this->name = $info['basename'];
//  MIME  
     $this->mime = mime_content_type($name);
//  
     $content = file_get_contents($name);
//      
     if($content!==false) $this->content = $content;
       else throw new Exception('Don`t get content - "'.$name.'"');
    } else throw new Exception('Error param');
  } else
     {
//   
      $this->name = $name;
//      MIME    
      if(is_null($mime)) $mime = mime_content_type($name);
//   MIME 
      $this->mime = $mime;
//      
      $this->content = $content;
     };
 }

//    
 public function Name() { return $this->name; }

//    MIME
 public function Mime() { return $this->mime; }

//    
 public function Content() { return $this->content; }

};
</pre>


الآن ، الفئة نفسها لتشكيل هيئة بيانات النموذج / متعددة الأجزاء لطلب POST:



<pre>
class BodyPost
 {
//    
  public static function PartPost($name, $val)
  {
   $body = 'Content-Disposition: form-data; name="' . $name . '"';
//     oFile
   if($val instanceof oFile)
    {
//   
     $file = $val->Name();
//  MIME  
     $mime = $val->Mime();
//   
     $cont = $val->Content();

     $body .= '; filename="' . $file . '"' . "\r\n";
     $body .= 'Content-Type: ' . $mime ."\r\n\r\n";
     $body .= $cont."\r\n";
    } else $body .= "\r\n\r\n".urlencode($val)."\r\n";
   return $body;
  }

//    POST    
  public static function Get(array $post, $delimiter='-------------0123456789')
  {
   if(is_array($post) && !empty($post))
    {
     $bool = false;
//       
     foreach($post as $val) if($val instanceof oFile) {$bool = true; break; };
     if($bool)
      {
       $ret = '';
//     ,   POST 
       foreach($post as $name=>$val)
        $ret .= '--' . $delimiter. "\r\n". self::PartPost($name, $val);
        $ret .= "--" . $delimiter . "--\r\n";
      } else $ret = http_build_query($post);
    } else throw new \Exception('Error input param!');
   return $ret;
  }
};
</pre>


تتكون هذه الفئة من عدة طرق. تشكل طريقة PartPost الأجزاء المنفصلة من الطلب المركب ، وتجمع طريقة Get بين هذه الأجزاء وتشكل نص طلب POST بالتنسيق - بيانات متعددة / نموذجية.



لدينا الآن فئة عامة لإرسال نص طلب POST. يبقى كتابة برنامج يستخدم هذه الفئة لإرسال الملفات إلى خادم ويب بعيد. دعنا نستخدم مكتبة CURL:



//  -  
include "ofile.class.php";
//      POST 
include "bodypost.class.php";

//       POST 
$delimiter = '-------------'.uniqid();

//   oFile  
$file = new oFile('sample.txt', 'text/plain', 'Content file');

//   POST 
$post = BodyPost::Get(array('field'=>'text', 'file'=>$file), $delimiter);

//   CURL
$ch = curl_init();

//      
curl_setopt($ch, CURLOPT_URL, 'http://server/upload/');
// ,    POST 
curl_setopt($ch, CURLOPT_POST, 1);
//   POST 
curl_setopt($ch, CURLOPT_POSTFIELDS, $post);

/*     :
     Content-Type -  , 
     boundary -   
     Content-Length -    */
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: multipart/form-data; boundary=' . $delimiter,
'Content-Length: ' . strlen($post)));

//  POST    Web 
curl_exec($ch);


إذا لم تكن CURL مناسبة ، فيمكن استخدام هذه المكتبة لإرسال المقابس. حسنًا ، في الواقع روابط إلى مصادر:





في المقالة التالية سأزودك بمعلومات حول كيفية تنزيل الملفات الكبيرة من خوادم الويب البعيدة في تدفقات متعددة بالسرعة المحددة. لكل من قرأ حتى النهاية ، أشكرك على اهتمامك!



All Articles