ما هو تحميل الملف؟
تحميل الملف هو حفظ معلومات المستخدم.
لماذا أحتاج إلى تحميل ملف؟
عندما يسجل المستخدم ، قد يحتاج المستخدم إلى إرسال صورة. ثم يجب حفظ هذه الصورة.
تحميل مكونات (أدوات) لماذا نحتاج إلى استخدام أداة التحميل؟
لماذا نحتاج إلى تحميل المكونات؟ عندما نريد الحصول على بيانات العميل ، عادة ما نحصل عليها من خلال طريقة getParameter ().
يتم تقسيم بيانات الملف التي تم تحميلها على بروتوكول MIME ، ويتم تغليف النموذج بالثنائي. بمعنى آخر: لا يمكن getParameter () الحصول على بيانات الملف الذي تم تحميله.
دعونا أولاً نلقي نظرة على كيفية تحميل ملفات HTTP للبيانات معك
صفحة JSP ، يجب تحديد النموذج envype: multipart/form-data
<form action = "$ {pagecontext.request.contextpath}/servlet/uploadservlet1" enctype = "multipart/form-data" method = "post"> upload user: <input type = "text" name = "username"> <br/> تحميل ملف 1: <input type = "file" name = "file2"> <br/> <input type = "submit" value = "subvice"> </pump>حزمة HTTP الاستيلاء
حاول الحصول على البيانات باستخدام getParameter () على servlet
String ss = request.getParameter ("username") ؛ system.out.println (ss) ؛لا يمكنك الحصول على البيانات عن طريق استخدام GetParameter مباشرة.
إذن ماذا يجب أن نفعل؟ ؟ ؟ ؟ يوفر كائن الطلب دفق ServleTinputStream لقراءة البيانات إلينا
نحاول قراءة الملف
servleTInputStream inputStream = request.getInputStream () ؛ بايت [] بايت = بايت جديد [1024] ؛ int len = 0 ؛ بينما ((len = inputStream.Read (bytes))> 0) {system.out.println (سلسلة جديدة (بايت ، 0 ، len)) ؛ }إضافة عنصر تحكم إضافي في الإدخال إلى صفحة JSP
<type type = "text" name = "password">
الملف النصي الذي قمت بتحميله هو 111111 ، وتأثير القراءة كما يلي:
الآن يمكننا قراءة بيانات تحميل الملفات ، ولكن الآن السؤال هو: كيفية فصل البيانات التي تم تحميلها للملف عن البيانات المرسلة إلى الخادم؟ ؟ ؟ لقد رأينا أعلاه في الصورة ، يتم خلطها معًا.
من الصعب فصل وفقًا لممارستنا المعتادة ، لذلك نحتاج إلى تحميل المكونات
هناك نوعان من مكونات تحميل fileUploads [المزيد من التشغيل] samrtupload [المزيد من العمليات] fileUpload
لاستخدام مكون FileUpload ، تحتاج إلى استيراد حزمتين جرة
Commons-Io Commons-Filepload Steps تنشئ كائن مصنع محلل [DiskfileItemFactory] إنشاء محلل من خلال مصنع المحلل [ServletFileUpload] استدعاء طريقة المحلل المحلل لتحليل كائن الطلب ، والحصول على جميع المحتويات المحملة [قائمة] بالتعقيد على القائمة ، تحديد ما إذا كان كل كائن ملفًا محمّلًا. إذا كان حقل النماذج العادي ، احصل على اسم الحقل وقيمة الحقل. إذا كان ملفًا تم تحميله ، فاتصل بأسلوب inputSteam للحصول على دفق الإدخال ، اقرأ البيانات التي تم تحميلها بسرعة.
حاول {// 1. احصل على مصنع مصنع Parser DiskfileItemFactory = New DiskfileItemFactory () ؛ // 2. احصل على تحميل servletfileupload المحلل = جديد servletfileupload (المصنع) ؛ // 3. حدد نوع نموذج التحميل إذا كان (! expload.ismultipartcontent (طلب)) {// تحميل النموذج هو نموذج عادي ، ثم الحصول على البيانات بالطريقة التقليدية للعودة ؛ } // لتحميل النموذج ، اتصل على المحلل لتحليل قائمة البيانات التي تم تحميلها <IbourItem> list = upload.parserequest (request) ؛ // fileitem // transfuse القائمة واحصل على كائن fileItem المستخدم لتغليف كائن بيانات عنصر إدخال أول تحميل لـ (fileItem item: list) {if (item.isformfield ()) {// ما تحصل عليه هو اسم سلسلة الإدخال العادي = item.getFieldName () ؛ // احصل على اسم قيمة سلسلة عنصر الإدخال = item.getString () ؛ System.out.println (name + "=" + value) ؛ } آخر {// احصل على fileName string expt induction = item.getName () ؛ // احصل على اسم ملف التحميل C:/المستندات والإعدادات/ThinkPad/Desktop/1.txt filename = filename.substring (filename.lastindexof ("//")+1) ؛ inputStream in = item.getInputStream () ؛ // الحصول على تحميل بيانات int len = 0 ؛ Byte Buffer [] = New Byte [1024] ؛ String SavePath = this.getServletContext (). getRealPath ("/expload") ؛ fileOutputStream Out = fileOutputStream جديد (SavePath + "//" + اسم الملف) ؛ // اكتب ملف إلى دليل التحميل بينما ((len = in.read (buffer))> 0) {out.write (buffer ، 0 ، len) ؛ } in.close () ؛ out.close () ؛ }}} catch (استثناء e) {E.PrintStackTrace () ؛ }اختبار أنه يمكن قراءة كل من الحقول العادية والملفات التي تم تحميلها!
smartupload
لاستخدام مكون smartupload ، تحتاج إلى استيراد حزمة تطوير smartupload.jar
بداية سريعة
// Instanted Component SmartUpload SmartUpload = new SmartUpload () ؛ // تهيئة عملية التحميل smartupload.initialize (this.getServletConfig () ، طلب ، استجابة) ؛ حاول {// تحميل إعداد smartupload.upload () ؛ // بالنسبة للبيانات العادية ، من السهل جدًا أن يتمكن كائن الطلب من الحصول على المعلمات المقدمة. أيضًا ، تحتاج إلى الاعتماد على كلمة مرور سلسلة SmartUpload = SmartUpload.getRequest (). getParameter ("كلمة المرور") ؛ System.out.println (كلمة المرور) ؛ // تحميل لتحميل Folder Smartupload.save ("exploadfile") ؛ } catch (SmartUploAdexception e) {E.PrintStackTrace () ؛ }امتحان
وبالمثل ، يمكننا تحميل الملفات إلى مجلد التحميل. يتم بالفعل تخفيض مقدار الكود كثيرًا!
يمكنك أيضًا الحصول على معلمات الحقول العادية
لقد غيرت اسم الملف إلى التعليمات البرمجية المشوهة الصينية والرمز المشتعل الصيني لتحميل البيانات ، وكان رمزًا مشوهًا:
البيانات الصينية المقدمة من النموذج مشوهة أيضا.
كما ذكر أعلاه ، يتم تغليف نموذج تحميل بيانات الملف بالثنائي ، لذلك لن يعمل طلب ترميز البيانات للبيانات المقدمة حسب النموذج!
FileUpload يحل الرمز المشوهة
استخدام FileUpload لحل المشكلات المشوهة أمر بسيط للغاية
حل اسم الملف الصيني المشوه. بعد الحصول على المحلل ، فقط اضبط ترميز المحلل إلى UTF-8!
// قم بتعيين ترميز تحميل fileUpload.SetHeaderenCoding ("UTF-8") ؛حل بيانات النموذج المشوهة. عند الحصول على قيم النماذج ، استخدم ترميز UTF-8 للحصول عليها.
string value = fileItem.getString ("utf-8") ؛تأثير:
SmartUpload يحل الرمز المشوهة
هذا المكون مزعج بعض الشيء لحل مشكلة التعليمات البرمجية المشوهة. لقد وجدت حلولًا مختلفة عبر الإنترنت ولكن لم أتمكن من العثور على حلقة بسيطة ...
لذلك ، إذا لم تتضمن البيانات الصينية ، فاستخدم مكون SmartUpload ، وإذا كانت تتضمن بيانات صينية ، فاستخدم مكون FileUpload!
قم بتحميل ملفات متعددة ، إضافة عناصر تحكم التحميل ديناميكيًا
لنفترض أن لديّ ملفات متعددة للتحميل الآن ، وعدد الملفات للتحميل غير مؤكد. إذن ماذا يجب أن نفعل؟ ؟ ؟
من المستحيل علينا سرد العديد من عناصر التحكم لتحميل الملفات على الصفحة ، وهو أمر غير جميل. إذا لم يتمكن المستخدم من استخدام العديد من عناصر التحكم ، فهذا مضيعة.
لذلك ، نريد إضافة عناصر تحكم ديناميكية لتحميل الملفات. إذا كان المستخدم يريد أيضًا تحميل الملفات ، فهو يحتاج فقط إلى إنشاء عناصر تحكم ديناميكية!
تحليل
لإنشاء عناصر التحكم ديناميكيًا على الصفحة ، فإنه ليس أكثر من استخدام رمز JavaScript.
إذن ماذا نفعل؟ ؟
دعنا نفعل ذلك: عندما يريد المستخدم تحميل ملف ، انقر فوق الزر ، ويربط الزر الحدث لإنشاء عنصر التحكم لتحميل الملف.
من أجل القيام أكثر بشكل مثالي ، كلما تم إنشاء عنصر تحكم في تحميل الملف ، يتم أيضًا توفير زر حذف لحذف عنصر التحكم!
يجب أن نستخدم Div لتحميل عناصر التحكم وحذف الأزرار التي نريد إنشاءها. عندما ينقر المستخدم على حذفه ، يجب عليهم إخفاء زر الحذف وعناصر تحكم تحميل الملف معًا. لذلك ، من الأفضل استخدام divs المتداخلة!
رمز رمز رمز:
<tably> <tr> <td> تحميل مستخدم: </td> <td> <type type = "text" name = "username"> </td> </tr> </tr> </table>
رمز JavaScript
<script type = "text/javaScript"> function adduploadfile () {// إنشاء تحكم في تحميل الملف var input = document.createElement ("input") ؛ input.type = 'file' ؛ input.name = 'filename' ؛ // إنشاء زر حذف var del = document.createElement ("input") ؛ del.type = 'button' ؛ del.value = 'delete' ؛ // إنشاء div var innerdiv = document.createElement ("div") ؛ // ربط اثنين من عناصر التحكم في innerdiv.appendchild (الإدخال) ؛ innerdiv.appendchild (del) ؛ // احصل على عنصر تحكم DIV الخارجي وربط div الداخلي إلى Div var الخارجي outterdiv = document.getElementById ("file") ؛ outterdiv.appendchild (innerdiv) ؛ // pind event del.onclick = function delete () {// استدعاء طريقة إزالة div الخارجية لقتل div الداخلية this.parentnode.parentnode.removechild (this.parentNode) ؛ }} </script>تفاصيل تحميل الملف إذا كان حجم الملف الذي تم تحميله أكبر من حجم الملف الذي نقوم بتعيينه ، فسيستخدم الملف ملفًا مؤقتًا لحفظ البيانات التي تم تحميلها عند التحميل. بعد التحميل ، يجب علينا حذف الملف المؤقت. لا يمكن إدارة الموقع الذي لا يمكن إدارة ملف التحميل بواسطة خادم الويب ، وإلا فقد يتسبب في مشاكل أمان [يمكن للآخرين تعديل ملف التحميل من خلال الوسائل] إذا كان اسم ملف التحميل هو نفسه ، فسيتم كتابة ملف التحميل الأصلي. نريد إنشاء اسم ملف فريد. إذا كان عدد المستخدمين كبيرًا ، فهناك العديد من الملفات التي تم تحميلها. بعد ذلك ، يجب ألا نحفظ جميع ملفات التحميل في دليل واحد ، والذي من المحتمل أن يتسبب في تعطل القرص. لذلك يتعين علينا تفريق الملفات التي تم تحميلها إلى أدلة مختلفة. تحليل
مشكلة حذف الملفات المؤقتة بسيطة للغاية. تحتاج فقط إلى استدعاء طريقة DELETE () لـ FileItem بعد اكتمال جميع العمليات.
لمنع إدارتها من قبل خادم الويب الذي تم تحميله ، يمكننا وضع موقع الملف الذي تم تحميله في الدليل/ الدليل!
لنفس اسم الملف ، يمكننا استخدام اسم الملف UUID+ تم تحميله بواسطة المستخدم كاسم ملف حفظنا. اسم الملف فريد من نوعه.
لتفكيك الملفات التي تم تحميلها ، نحتاج إلى استخدام خوارزمية HashCode لتفكك.
تقوم الأجزاء الأربعة السفلية بإنشاء دليل من المستوى الأول 5-8 بت أن إنشاء رمز الدليل من المستوى الثاني
دعنا نكتب رمز ملف التحميل الكامل نسبيًا
استخدم خوارزمية Hashcode لتفكيك الدلائل المحفوظة
سلسلة خاصة makedirpath (اسم ملف السلسلة ، مسار السلسلة) {// احسب الدلائل الأساسية والثانوية من خلال اسم الملف int hashcode = filename.hashCode () ؛ int dir1 = hashcode & 0xf ؛ int dir2 = (hashcode & 0xf0) >> 4 ؛ سلسلة dir = path + "//" + dir1 + "//" + dir2 ؛ // إذا لم يكن الدليل موجودًا ، فقم بإنشاء ملف دليل الدليل = ملف جديد (dir) ؛ if (! file.exists ()) {file.mkdirs () ؛ } // إرجاع المسار الكامل لإرجاع dir ؛ }إنشاء أسماء ملفات فريدة
سلسلة خاصة makefilename (اسم ملف السلسلة) {// استخدم UndersCore لفصل UUID واسم الملف ، وقد يتم تحليل اسم الملف لاحقًا. إرجاع uuid.randomuuid (). toString () + "_" + اسم الملف ؛ }رمز تم تحميله
// إنشاء مصنع DiskfileItemFactory المصنع = جديد diskfileItemFactory () ؛ // إنشاء محلل من خلال المصنع servletfileupload fileUpload = new servletfileupload (Factory) ؛ // قم بتعيين رمز التحميل fileUpload.SetHeaderenCoding ("UTF-8") ؛ // تحكم على نوع نموذج التحميل if (! fileUpload.ismultipartContent (request)) {// قم بتحميل النموذج كنموذج عادي ، ثم الحصول على البيانات بالطريقة التقليدية للعودة ؛ } جرب {// تحليل كائن الطلب للحصول على قائمة [قم بتحميل جميع المحتوى المحمّل] قائمة <FileItem> list = fileupload.parserequest (request) ؛ // السفر عبر القائمة لتحديد ما إذا كان المحتوى المحمّل هو حقل عادي أو ملف تحميل لـ (FileItem fileItem: list) {// إذا كان عنصر إدخال عادي إذا (fileitem.isformfield ()) {// احصل على اسم وقيمة اسم عنصر الإدخال = fileItem.getFieldName () ؛ string value = fileItem.getString ("utf-8") ؛ System.out.println (name + "=" + value) ؛ } آخر {// إذا كان ملف تحميل // احصل على اسم التحميل [بما في ذلك اسم المسار] filename = fileItem.getName () ؛ // اعتراض اسم الملف filename = filename.substring (filename.lastindexof ("//") + 1) ؛ // إنشاء اسم ملف اسم ملف فريد = makefilename (اسم الملف) ؛ inputStream inputStream = fileItem.getInputStream () ؛ // احصل على مسار المشروع واكتب الملف الذي تم تحميله إلى مسار سلسلة المشروع = this.getServletContext (). // احصل على سلسلة مسار الدليل المبعثرة realPath = makedirpath (اسم الملف ، المسار) ؛ FileOutputStream OutputStream = جديد fileOutputStream (RealPath + "//" + اسم الملف) ؛ بايت [] بايت = بايت جديد [1024] ؛ int len = 0 ؛ بينما ((len = inputStream.Read (bytes))> 0) {outputStream.write (bytes ، 0 ، len) ؛ } inputStream.close () ؛ outputStream.Close () ؛ // حذف بيانات الملف المؤقت FileItem.Delete () ؛ }}} catch (fileUploAdexception e) {e.printStackTrace () ؛ }التأثير: تم تقسيم الدليل بنجاح ، وكان اسم الملف فريدًا.
سرد الملفات في الدليل الذي تم تحميله وقدم التنزيلات
عند شرح كائن Respose ، تم شرح تنزيل الملف. هذه المرة سوف نكتب حالة صغيرة لتوحيد تنزيل الملف.
هناك 3 ملفات في دليل التحميل
تحليل
أولاً ، سرد جميع الملفات في الدليل. نظرًا لأننا نحتاج إلى تنزيل الملف وفقًا لاسم الملف لاحقًا ، فإننا نستخدم مجموعة خريطة لحفظ جميع الملفات
جزء التنزيل بسيط للغاية. ابحث عن الملف المقابل وفقًا لاسم الملف وتحميل موقع الملف ، وقراءته واكتبه ، ثم قم بتعديل رأس الرسالة لتحقيق التنزيل.
احصل على المسار لتحميل الملفات وتحميلها ، واكتشف جميع الملفات بشكل متكرر (الحكم على ما إذا كان ملفًا أو مخرجًا متكررًا) ، وقم بتحميله في مجموعة الخريطة وقم بتمرير مجموعة الخريطة إلى مكتب الاستقبال لعرضه عندما ينقر المستخدم على التنزيل ، ثم الحصول على المسار المطلق وفقًا للاسم الأصلي. في حالة وجود المورد ، يُسمح للمستخدم بتنزيل الكود ووضع جميع الملفات المخزنة في الدليل/ الدليل في مجموعة الخريطة.
DOPOST الفراغ المحمي (طلب httpservletrequest ، استجابة httpservletresponse) يلقي servletexception ، ioException {// الحصول على الدليل حيث الملف المحمّل هو سلسلة filePath = this.getServletContext (). خريطة الخريطة = new hashmap () ؛ // استخدم Recursion للحصول على جميع الملفات وإضافتها إلى GetAllfiles Collection Map (ملف جديد (FilePath) ، MAP) ؛ request.setAttribute ("Map" ، MAP) ؛ request.getRequestDispatcher ("/listfile.jsp"). } private void getAllfiles (filepath ، خريطة الخريطة) {// إذا لم يكن ملفًا ، فهو مجلد إذا (! filepath.isfile ()) {// اذكر جميع الملفات في المجلد (ربما ملف ، ربما مجلد) ملف = filepath.listfiles () ؛ لـ (ملف الملف: الملفات) {// upply the file (أو المجلد) و getAllFiles (ملف ، خريطة) ؛ }} else {// أدخل عبارة else ، يجب أن يكون ملفًا // الحصول على اسم ملف اسم الملف = filePath.getName (). // نقوم بحفظ الاسم الكامل للملف كمفتاح واسم الملف كقيمة في مجموعة MAP Map.put (filePath.getName () ، اسم الملف) ؛ }}عرض الملفات القابلة للتنزيل في صفحة JSP
<c: foreach heads = "$ {map}" var = "me"> <c: url var = "url" value = "/downfileservlet"> <c: param name = "filename" value = "$ {me </a> <br> </c: foreach>قم بتنفيذ Servlet الذي تم تنزيله
DOPOST الفراغ المحمي (طلب httpservletrequest ، استجابة httpservletresponse) يلقي servleTexception ، ioException {// احصل على الاسم الكامل لسلسلة الملف fileName = request.getParameter ("Filename") ؛ // إذا كانت البيانات الصينية ، فمن المطلوب ترميز. filename = سلسلة جديدة (filename.getBytes ("ISO8859-1") ، "UTF-8") ؛ // احصل على الموقع الذي يتم فيه حفظ الملف string path = this.getServletContext (). getRealPath ("/web-inf/uploadfile") ؛ // يتم حفظ الملف من خلال اسم الملف بواسطة HashCode ، ويتم الحصول على الملف من خلال سلسلة اسم الملف FileRealPath = MakefilePath (اسم الملف ، المسار) ؛ System.out.println (FilerealPath) ؛ // الحكم على ما إذا كان الملف موجودًا ملف ملف = ملف جديد (FileRealPath) ؛ if (! file.exists ()) {request.setattribute ("message" ، "المورد الذي تريد تنزيله غير موجود!") ؛ request.getRequestDispatcher ("/message.jsp"). يعود ؛ } // موجودة // اقرأ الملف واكتب البيانات إلى المتصفح fileInputStream inputStream = جديد fileInputStream (filerealpath) ؛ بايت [] بايت = بايت جديد [1024] ؛ int len = 0 ؛ بينما ((len = inpectStream.Read (bytes))> 0) {reception.getOutputStream (). الكتابة (البايت ، 0 ، len) ؛ } inputStream.close () ؛ // قم بتعيين رأس الرسالة لإخبار المتصفح بأن هذا هو اسم سلسلة الملفات التي تم تنزيلها = filename.substring (filename.lastindexof ("_") + 1) ؛ استجابة. } سلسلة خاصة makefilepath (اسم ملف السلسلة ، مسار السلسلة) {int hashcode = filename.hashCode () ؛ int dir1 = hashcode & 0xf ؛ int dir2 = (hashcode & 0xf0) >> 4 ؛ String dir = path + "//" + dir1 + "//" + dir2 + "//" + filename ؛ إرجاع دير }تأثير
إذا كان هناك أي خطأ في المقالة ، فيرجى تصحيحني وسيتواصل الجميع مع بعضهم البعض. شكرا لك على دعمك إلى wulin.com.