Advertisement
  1. Web Design
  2. Web Development

تحميل ملفات مع أياكس

Scroll to top
Read Time: 9 min

() translation by (you can also view the original English article)

لا يمكنني الوصول إلى نهاية الأشياء المرحة التي يمكنك فعلها باستخدام تقنيات الويب الناشئة. اليوم ، سوف أريكم كيفية القيام بشيء ما - إلى حين آخر - لم يسبق له مثيل تقريباً: تحميل الملفات عبر AJAX.

وه ، بالتأكيد ، هناك تم اختراق ؛ ولكن إذا كنت مثلي ، وتشعر بالسوخ في كل مرة تكتب فيها iframe ، فستعجبك كثيرًا. الانضمام لي بعد القفزة!

هل تبحث عن حل سريع؟

إذا كنت تبحث عن حل سريع، هناك مجموعة كبيرة من البرامج النصية لتحميل الملفات وتطبيقات أكثر في الأسواق Envato.

برنامج تحميل ملفات HTML5 هذا أنيق بشكل خاص - يمكنك إضافة الملفات بسهولة عن طريق السحب والإفلات أو النقر كافة الملفات التي سيتم تحميلها عن طريق AJAX أو يمكن إضافتها ضمن نموذج، ويمكن إعادة تسمية الملفات قبل تحميلها. حل كبيرة وسريعة إذا كان هذا ما كنت تبحث عن!


لماذا لا يمكننا الحصول على الأخبار السيئة أكثر مع؟

هذا لا يعمل في كل متصفح. ومع ذلك ، مع بعض التحسينات التدريجية (أو أيا كانت الكلمة الطنانة الحالية) ، فستكون لدينا صفحة تحميل ستعود إلى الإصدار IE6 (على الرغم من عدم وجود بتات AJAXy).

سيعمل تحميل AJAX الخاص بنا طالما أن FormData متاح ؛ خلاف ذلك ، سيحصل المستخدم على تحميل عادي.

هناك ثلاثة مكونات رئيسية لمشروعنا.

  • السمة multiple على عنصرinputالملف.
  • كائن FileReader من ملف API الجديد.
  • الكائن FormData من XMLHttpRequest2.

نستخدم السمة multiple للسماح للمستخدم بتحديد عدة ملفات للتحميل (سيعمل التحميل المتعدد للملفات بشكل طبيعي حتى إذا لم يكن FormData متاحًا). كما سترى ، FileReader يسمح لنا بإظهار الصور المصغرة للمستخدم من الملفات التي يتم تحميلها (سنكون نتوقع الصور).

لا تعمل أي من ميزاتنا الثلاثة في IE9 ، لذلك سيحصل جميع مستخدمي IE على تجربة تحميل عادية (على الرغم من أنني أفهم أن دعم `FileReader` متوفر في IE10 Dev Preview 2). لا يعمل FileReader في أحدث إصدار من Safari (5.1) ، لذا لن يحصلوا على الصور المصغرة ، لكنهم سيحصلون على تحميل AJAX ورسالة التأكيد. أخيرًا ، يحتوي Opera 10.50 على دعم FileReader ولكن ليس دعم FormData ، لذلك سيحصلون على صور مصغرة ، ولكن تحميلات عادية.

مع أن الخروج من الطريق، دعونا الحصول على الترميز!


الخطوة 1: توصيف والتصميم

دعونا نبدأ مع بعض العلامات الأساسية والتصميم. بالطبع، ليس هذا هو الجزء الرئيسي من هذا البرنامج التعليمي، لن يعاملك مثل مبتدئ.

ال HTML

1
<!DOCTYPE html>
2
<html lang="en">
3
<head>
4
  <meta charset="UTF-8" />
5
  <title>HTML5 File API</title>
6
  <link rel="stylesheet" href="style.css" />
7
</head>
8
<body>
9
  <div id="main">
10
    <h1>Upload Your Images</h1>
11
    <form method="post" enctype="multipart/form-data"  action="upload.php">
12
      <input type="file" name="images" id="images" multiple />
13
      <button type="submit" id="btn">Upload Files!</button>
14
    </form>
15
16
    <div id="response"></div>
17
    <ul id="image-list">
18
19
    </ul>
20
  </div>
21
22
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
23
  <script src="upload.js"></script>
24
</body>
25
</html>

جميلة جدا ، ايه؟ لقد حصلنا على نموذج نشر على upload.php ، والذي سننظر إليه في عنصر ثانٍ ، وعنصر إدخال فردي ، من file  الكتابة. لاحظ أنه يحتوي على السمة المنطقية multiple ، والتي تسمح للمستخدم بتحديد ملفات متعددة في وقت واحد.

هذا كل شيء حقاً أن نرى هنا وهناك. دعنا ننتقل.

CSS

1
body {
2
  font: 14px/1.5 helvetica-neue, helvetica, arial, san-serif;
3
  padding:10px;
4
}
5
6
h1 {
7
  margin-top:0;
8
}
9
10
#main {
11
  width: 300px;
12
  margin:auto;
13
  background: #ececec;
14
  padding: 20px;
15
  border: 1px solid #ccc;
16
}
17
18
#image-list {
19
  list-style:none;
20
  margin:0;
21
  padding:0;
22
}
23
#image-list li {
24
  background: #fff;
25
  border: 1px solid #ccc;
26
  text-align:center;
27
  padding:20px;
28
  margin-bottom:19px;
29
}
30
#image-list li img {
31
  width: 258px;
32
  vertical-align: middle;
33
  border:1px solid #474747;
34
}

على الإطلاق لا صدمة هنا.


الخطوة 2: بي إتش بي

يجب أن نكون قادرين على التعامل مع عمليات تحميل الملفات في النهاية الخلفية أيضًا ، لذلك دعنا نغطي ذلك بعد ذلك.

upload.php

1
<?php
2
3
foreach ($_FILES["images"]["error"] as $key => $error) {
4
  if ($error == UPLOAD_ERR_OK) {
5
    $name = $_FILES["images"]["name"][$key];
6
    move_uploaded_file( $_FILES["images"]["tmp_name"][$key], "uploads/" . $_FILES['images']['name'][$key]);
7
  }
8
}
9
10
echo "<h2>Successfully Uploaded Images</h2>";

ضع في اعتبارك أن هذه هي الخطوط الأولى من PHP التي كتبتها في سنة واحدة بسهولة (أنا شخص روبي). ربما ينبغي عليك أن تفعل المزيد للأمن ؛ ومع ذلك ، فنحن ببساطة نتأكد من عدم وجود أخطاء في التحميل. إذا كانت هذه هي الحالة ، فنحن نستخدم الملف move_uploaded_file المضمن لنقله إلىuploadsالتحميلات. لا تنس أن تتأكد من أن المجلد قابل للكتابة.

لذا، الآن، ينبغي أن يكون لدينا عمل تحميل النموذج. يمكنك اختيار صورة (متعددة، إذا تريد وتمكنك من المستعرض الخاص بك)، انقر فوق الزر "تحميل الملفات"!، وكنت احصل على الرسالة "بنجاح حملت الصور."

هنا ما يبدو لنا مشروع صغير مثل حتى الآن:

The styled formThe styled formThe styled form

لكن ، هيا ، إنه عام 2011: نريد أكثر من ذلك. ستلاحظ أننا ربطنا jQuery وملف upload.js. دعونا نكسر ذلك الان


الخطوة 3: جافا سكريبت

دعونا لا نضيع الوقت: ونحن هنا الذهاب!

1
(function () {
2
  var input = document.getElementById("images"),
3
      formdata = false;
4
    
5
  if (window.FormData) {
6
    formdata = new FormData();
7
    document.getElementById("btn").style.display = "none";
8
  }
9
  
10
11
}();

إليك ما نبدأ به. نخلق متغيرين: input هي عنصر إدخال الملفات ؛ سيتم استخدام formdata لإرسال الصور إلى الخادم إذا كان المستعرض يدعم ذلك. نقوم بتهيئته إلى false ومن ثم التحقق لمعرفة ما إذا كان المستعرض يدعم FormData؛ إذا حدث ذلك ، فسننشئ كائن FormData جديدًا. أيضا، إذا كان يمكننا تقديم الصور مع أياكس، لا نحتاج الزر "تحميل الصور!"، حيث يمكن أن نخفي ذلك. لماذا لا نحن في حاجة إليها؟ حسنا، نحن ذاهبون للسيارات سحرية تحميل الصور مباشرة بعد أن يقوم المستخدم بتحديد لهم.

سوف يذهب بقية جافا سكريبت داخل الدالة الخاصة بك استدعاء ذاتي مجهول. ونحن بعد ذلك بإنشاء وظيفة مساعد قليلاً سوف تظهر الصور بمجرد المستعرض لها:

1
function showUploadedItem (source) {
2
  var list = document.getElementById("image-list"),
3
      li   = document.createElement("li"),
4
      img  = document.createElement("img");
5
    img.src = source;
6
    li.appendChild(img);
7
  list.appendChild(li);
8
}

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

بعد ذلك ، يتعين علينا بالفعل التقاط الصور وعرضها وتحميلها. وكما قلنا ، سنفعل ذلك عند تشغيل حدث onchange على عنصر الإدخال.

1
if (input.addEventListener) {
2
  input.addEventListener("change", function (evt) {
3
    var i = 0, len = this.files.length, img, reader, file;
4
    
5
    document.getElementById("response").innerHTML = "Uploading . . ."
6
    
7
    for ( ; i < len; i++ ) {
8
      file = this.files[i];
9
  
10
      if (!!file.type.match(/image.*/)) {
11
12
      } 
13
    }
14
      
15
  }, false);
16
}

نحن لا داعي للقلق حول نموذج الحدث الملكية لشركة أي أي، نظراً لأن IE9 + يعتمد الدالة القياسية أديفينتليستينير.

هناك المزيد ، لكن لنبدأ بهذا. أولاً ، لا داعي للقلق بشأن نموذج الحدث المملوك لشركة IE ، نظرًا لأن IE9 + يدعم وظيفة addEventListener القياسية (ولا يدعم IE9 أو أحدث ميزاتنا الجديدة).

لذا، ما نريد القيام به عند قيام المستخدم باختيار الملفات؟ أولاً، نحن إنشاء متغيرات قليلة. حق واحد فقط المهم الآن هو len = this.files.length. الملفات التي قام المستخدم بتحديده سيكون موجوداً من this.files الكائن. الحق الآن، نحن قلقون من إلا مع خاصية length، حيث أننا يمكن أن يتكرر أكثر من الملفات...

... وهو بالضبط ما نفعله بعد. داخل لدينا حلقة، وضعنا الحالي fileإلى ملف لسهولة الوصول إليها. القادم شيء نفعله هو التأكد من أن الملف صورة. يمكننا القيام بذلك عن طريق مقارنة خاصية typeمع التعبير العادي. نحن نبحث عن نوع يبدأ بـ "image" ويتبعه أي شيء. (إن الدوي المزدوج في الأمام يحول النتيجة إلى قيمة منطقية.)

لذا، ماذا نفعل إذا كانت لدينا صورة في أيدينا؟

1
if ( window.FileReader ) {
2
  reader = new FileReader();
3
  reader.onloadend = function (e) { 
4
    showUploadedItem(e.target.result);
5
  };
6
  reader.readAsDataURL(file);
7
}
8
if (formdata) {
9
  formdata.append("images[]", file);
10
}

نتحقق مما إذا كان المستعرض يدعم إنشاء كائنات FileReader أم لا. إذا حدث ذلك ، فسننشئ واحدًا.

إليك كيفية استخدام كائن FileReader: سننقل كائن الملف إلى طريقة reader.readAsDataURL. يؤدي ذلك إلى إنشاء عنوان url للبيانات للصورة التي تم تحميلها. أنها لا تعمل بالطريقة التي قد تتوقع، على الرغم. ليس تمرير url البيانات مرة أخرى من الدالة. بدلاً من ذلك، سوف يكون url البيانات جزء من كائن الحدث.

مع وضع ذلك في الاعتبار ، سنحتاج إلى تسجيل وظيفة على حدث reader.onloadend. تأخذ هذه الوظيفة كائن حدث ، نحصل على عنوان url البيانات: في e.target.result (نعم ، e.target هو كائن reader ، ولكن كان لدي مشاكل عند استخدام reader بدلا من e.target داخل هذه الوظيفة) . سنقوم فقط بتمرير عنوان URL الخاص بالبيانات إلى وظيفة showUploadedItem الخاصة بنا (التي كتبناها أعلاه).

بعد ذلك ، نتحقق من وجود كائن formdata. تذكر ، إذا كان المستعرض يدعم FormData ، سيكون formdata كائن FormData؛ خلاف ذلك ، سيكونfalse. لذلك ، إذا كان لدينا كائن FormData ، فسنستدعي طريقة append. الغرض من كائن FormData هو الاحتفاظ بالقيم التي ترسلها عبر نموذج ؛ لذلك ، فإن أسلوب append ببساطة يأخذ مفتاح وقيمة وفي حالتنا، لدينا المفتاح صور []؛ بإضافة الأقواس-تحقيقا للغاية، علينا أن نتأكد من كل الوقت ونحن إلحاق قيمة أخرى، نحن كنت إلحاق فعلا لأن الصفيف، بدلاً من الكتابة فوق الخاصية الصورة.

نحن على وشك الانتهاء. في الحلقة الدراسية لدينا ، لقد عرضنا كل صورة للمستخدم وأضفناها إلى كائن formdata. الآن ، نحن بحاجة فقط إلى تحميل الصور. خارج الحلقة ، إليك الجزء الأخير من اللغز:

1
if (formdata) {
2
  $.ajax({
3
    url: "upload.php",
4
    type: "POST",
5
    data: formdata,
6
    processData: false,
7
    contentType: false,
8
    success: function (res) {
9
      document.getElementById("response").innerHTML = res; 
10
    }
11
  });
12
}

مرة أخرى ، يجب أن نتأكد من أن لدينا دعم FormData ؛ إذا لم نفعل ذلك ، فسيكون زر "تحميل الملفات" مرئيًا ، وهذا هو الكيفية التي سيحمّل بها المستخدم الصور. ومع ذلك، إذا كان لدينا دعم فورمداتا، نحن تأخذ الرعاية من تحميلها عبر AJAX. نحن نستخدم مسج للتعامل مع جميع الشذوذ أياكس عبر المتصفحات.

ربما تكون على دراية بطريقة jajuery’s $ .ajax: يمكنك تمريرها إلى كائن خيارات. يجب أن يكون عنوان URL ونوع وخصائص النجاح واضحًا. خاصية البيانات هي كائن شكل البيانات الخاص بنا. لاحظ هذه الخصائص processData ونوع المحتوى. ووفقا لوثائق مسج، processData صحيح بشكل افتراضي، وسوف عملية وتحويل البيانات إلى سلسلة استعلام. لا نريد القيام بذلك ، لذا قمنا بتعيين ذلك على "false". نحن أيضًا بصدد تعيين contentType على false للتأكد من وصول البيانات إلى الخادم كما نتوقعه.

وهذا كل شيء. الآن، عندما يحمل المستخدم الصفحة، يرون هذا:

Tutorial ImageTutorial ImageTutorial Image

وبعد تحديد الصور ، سيظهر لهم هذا:

Tutorial ImageTutorial ImageTutorial Image

وتم تحميل الصور:

Tutorial Image

وهذا هو التفاف!

يعد تحميل الملفات عبر AJAX أمرًا رائعًا ، ومن الرائع أن تدعم هذه التقنيات الجديدة ذلك دون الحاجة إلى اختراق طويل. إذا كنت قد تلقيت أي أسئلة حول ما فعلناه هنا ، فانتقل إلى هذه التعليقات! شكرا جزيلا لقراءتك!

وإذا كانت لا تزال تحتاج إلى مساعدة مع هذه المشكلة أو أي مسألة أخرى الترميز، تجد الدعم في الاستوديو Envato.

Advertisement
Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Web Design tutorials. Never miss out on learning about the next big thing.
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.