ادركت (عندما تبحث نفسي) أن هناك الكثير من العروض والدروس التي تبين لكم كيف لسحب وإسقاط الملفات في المتصفح ثم جعله على الصفحة. انهم غالبا ما وصفت بأنها “السحب والإفلات وتحميل”, لكنها في الواقعلا تحميل. هذا البرنامج التعليمي سوف تتخذ لكم أن الخطوة الأخيرة.
سوف المشي لكم من خلالعلى سبيل المثال يمكن أن تقوم به مع: اسحب الملف إلى صفحة ويب, وأنه سوف يتم تحميلها على الخادم على الفور.
مهام#
دعونا كسر هذه العملية وصولا إلى مهام محددة:
- التقاط الحدث قطرة وقراءة بياناتها.
- أضف أن البيانات الثنائية إلى ملقم.
- قدم ملاحظاتك عن التقدم للتحميل.
- اختياريا تقديم معاينة ما يجري تحميلها ومكانتها.
ولتحقيق كل هذا, نحن بحاجة إلى HTML5 التالية وغير HTML5 واجهات برمجة التطبيقات:
نضع في اعتبارنا أنه ليس كل المتصفحات تدعم كل من هذه التكنولوجيا اليوم, لكنهم الاقتراب. أردت فقط أن إنشاء برنامج تعليمي واضح وكامل عن كيفية الذهاب حتى النهاية وتحميل أن تراجع ملف.
النتيجة النهائية: ونحن قادرون على إسقاط الملف في أي مكان في المتصفح, نحصل على المعاينة وتقدم التحميل, وانها تجربة البقعة.

السحب والإسقاط#
تماما كما إنذار مسبق, السحب والإفلات كان من المعروف أن يكون نوعا من هادم اللذات. في الواقع, انه كابوس, ولكن لن أكرر ما كانقالقبل.
مثالنا سوف تسمح لك لسحب وإسقاط الملفات في أي مكان داخل المتصفح. لتحقيق ذلك, نحن بحاجة إلى إرفاق المستمعين الحدث لدينا لbody
أوdocumentElement
(أي, العقدة HTML الجذر). من خلال الاستماع علىdocumentElement
, هذا الرمزاستطاع تكون في أي مكان في الصفحة, مثلdocumentElement
سيكون موجودا دائما. يمكنك الاستماع فقط علىbody
مرة واحدة في<body>
تم مصادفة عنصر.
ها هي نمط من التعليمات البرمجية نحتاج لالتقاط الحدث انخفاض على المستند بأكمله:
var doc = document.documentElement; doc.ondragover = function () { this.className = 'hover';return false; }; doc.ondragend = function () { this.className = ''; returnfalse; }; doc.ondrop = function (event) { event.preventDefault && event.preventDefault(); this.className = ''; // now do something with: var files = event.dataTransfer.files; return false; };
أنا باستخدامhover
الفئة بحيث يمكنني تبديل تلميح شرح للمستخدم أن الملف يمكن الاستغناء عنها على الصفحة.
داخلdrop
هدف, يمكننا الوصول إلى الملفات انخفض عبرevent.dataTransfer.files
.
بديل لسحب وإسقاط#
مزعج, وأنا أكتب هذا, وأنا أدرك هذا المزيج من متطلبات API حاليا مواجهتها إلا كروم وفايرفوكس. وبالتالي, أخذ الاختبار منModernizr, يمكننا اختبار للحصول على دعم وتوفير بديل لدينا:
var dndSupported = function () { var div = document.createElement('div'); return ('draggable' in div) || ('ondragstart' in div &&'ondrop' in div); }; if (!dndSupported()) { // take alternative route }
بدلا من السحب والإفلات, يمكننا إدراج عنصر ملف الإدخال (لقد أعطيت لid
من “رفع”), وعندما يتم تغيير قيمة لها, يمكن حصد الملف في:
document.getElementById('upload').onchange = function (event){ // `this` refers to the element the event fired upon var files = this.files; };
يمكنك ان ترى ما يعادل هو ببساطةfiles
ملكا للHTMLInputElement
موضوع. هذا سيتيح لنا الوصول إلى نفس الملف باسمevent.dataTransfer.files
من الحدث قطرة.
تحميل تلقائيا ملف#
هذا هو الشيء أنيق, وانها بسيطة مؤلم. نحن نستخدم ميزة من المواصفات XHR2: FormData
. وبمجرد أن إنشاء مثيلFormData
, يمكننا إلحاق العناصر إليها:
var formData = new FormData(); for (var i = 0; i < files.length; i++) { formData.append('file', files[i]); } // now post a new XHR request var xhr = new XMLHttpRequest(); xhr.open('POST', '/upload'); xhr.onload = function () { if (xhr.status === 200) { console.log('all done: ' + xhr.status); } else { console.log('Something went terribly wrong...'); } }; xhr.send(formData);
FormData
بلى, هذا هو.†
دعونا ننظر في زوجين من الامور المهمة التي تجري رمز أعلاه.
formData.append('file', files[i]);
إننا نبعث المعلمات اسمه إلى خادمنا, على وجه التحديد مجموعة من القيم تسمىfile
. بوضوح, يمكنك تسميتها ما تريد, لكن الfile
هو اسم سوف تبحث الخادم الخاص بك لأنه عندما يقوم بحفظ الملف الذي تم تحميله (أو ملفات).
xhr.onload = function () { if (xhr.status === 200) { console.log('all done: ' + xhr.status); } else { console.log('Something went terribly wrong...'); } };
إذا كنت على دراية XHR, ستلاحظ أننا لا تستمع لonreadystatechange
, فقطonload
- الذي (في الواقع) وظيفة الراحة لتمكنك من معرفة متىreadyState
هو 4 (أي, محمل!). يجب أن لا تزال تحقق والرد بشكل مناسب على رمز حالة الطلب لضمان انها 200 حسنا, بدلا من 500 (خطأ في الخادم الداخلي) أو 404 (غير معثور عليه) او اي شيء اخر.
xhr.send(formData);
خدعة لطيفة هنا هي أن XHR وقد وضعت تلقائيا ترميز البيانات التي تم نشرها لmultipart/form-data
. هذا الترميز يسمح الخادم الخاص بك لقراءة وحفظ ملفات. انها مثل الترميز المستخدم عند إرسال مرفق في رسالة بالبريد الالكتروني.
تقديم ملاحظات إلى العضو#
XHR2 الآن (فليبين’ أخيرا) يأتي معprogress
هدف. حتى إذا كنت إرسال أو استرداد الملفات الكبيرة عبر XHR, يمكن أن أقول لكم المستخدم مدى طول كنت.
انها بسيطة جدا. إذا كنت تريد أن تتبع التقدم المحرز في طلب XHR, الاستماع إلىprogress
هدف. واحد مسكتك التي اشتعلت لي لبعض الوقت: كنت بحاجة لتتبع التقدم المحرز فيرفع, ليس تحميل. للقيام بذلك بشكل صحيح, كنت بحاجة للاستماع للتقدم علىتحميل XHR موضوع, وذلك:
xhr.upload.onprogress = function (event) { if (event.lengthComputable) { var complete = (event.loaded / event.total * 100 | 0); progress.value = progress.innerHTML = complete; } }; xhr.onload = function () { // just in case we get stuck around 99% progress.value = progress.innerHTML = 100; };
progress
هدفلاحظ أنه بدلا منxhr.onprogress
, نحن نستخدمxhr.upload.onprogess
. عندما حرائق هذا الحدث, نتحقق من أن الحدث يدعم احتساب كمية البيانات التي يتم تحميلها (الlengthComputable
جزء), ومن ثم حساب كمية الانتهاء.
في بلدي HTML, أنا باستخدام<progress>
جزء (مشابهه ل<meter>
جزء, ولكن أكثر ملاءمة لغويا كما نقوم بتقديم التقدم مهمة) لتظهر للمستخدم كم من الملفات الخاصة بهم تم تحميل:
<معرف التقدم ="تقدم" I ="0" الحد الأقصى ="100"القيمة ="0">0</تقدم>
علما بأنني أستخدمinnerHTML
لمتصفحات التي لا تدعم حتى الآن<progress>
. ثم مع اندفاعة من المحتوى المقدم CSS, كلا الinnerHTML
وvalue
التقدم يمكن أن تكون هي نفسها (ربما يكون الأمثل على, لكنني فخور بدلا من نفسي في ذلك الوقت!).
وأخيرا, تقديم معاينة#
كما لطيفة، بالإضافة, we’ll give the user a preview of what we’re uploading for them. It requires theFile API — specifically theFileReader
API.
As the drag-and-drop operation (or theinput[type=file]
) contains a file object, we can hand this over to theFileReader
to get the contents of the file. If it’s something like an image, we can get the Base64 data and give the user a preview. Or if it’s text, we could render it in a<div>
. The MIME type for the file is available as thetype
property on the file object.
So let’s assume we only accept images. وهنا يكمن جزء المعاينة التي تدير بعد أن تم استلام الملف عن طريق المتصفح:
var acceptedTypes = { 'image/png': true, 'image/jpeg': true, 'image/gif': true }; if (acceptedTypes[file.type] === true) { var reader = new FileReader(); reader.onload = function (event) { var image = new Image(); image.src = event.target.result; image.width = 100; // a fake resize document.body.appendChild(image); }; reader.readAsDataURL(file); }
نخلقFileReader
واعطائها ملف لقراءة. في المثال أعلاه, لقد استعملتreadAsDataURL
, ولكن يمكنك أيضا قراءة الملفات في نص عادي والأشكال الثنائية (حسب المواصفات).
عندما القارئ قد قرأ الملف والبيانات متاح, انها تطلق علىload
هدف, وهذا بدوره يخلق لدينا صورة جديدة.
النتيجة الملف قراءة العمل هو فيevent.target.result
خاصية. في حالةreadAsDataURL
, كانت القيمة على غرارdata:image/png;base64,ABC...
.
باستخدام كل الأدوات في السقيفة#
قد يكون هذا المثال مفتعلة قليلا لهذه المادة التي أردت أن أكتب. لقد استعملت العديد من التقنيات المختلفة أن تفعل شيئا وهذا هو نمط شائع إلى حد كبير على شبكة الإنترنت. في الواقع, كان لأنه كان يجد صعوبة في العثور على المصدر النهائي حول تحميل لفعلي الخادم (إلا, بالطبع بكل تأكيد, كما كتبت هذا المقال وجدتهذا المثال من الخلف في وقت متأخر 2010!).
نأمل, سترى كيف أن كل شيء من التكنولوجيا يمكن أن تعمل معا لإنشاء تطبيق, ولكن على قدم المساواة وآمل أن تتمكن من رؤية أين هذا من شأنه أن يعمل إذا أو مجرد بعض من التكنولوجيا كان لا شيء غير متوفر. تأكد من الكشف عن وظائف. تأكد من توفير fallbacks. تأكد من وضع المسؤولية.
وهنا نهائيالسحب والإفلات وتحميل تجريبي بالنسبة لك للعب مع.