• 0
herch

رفع ملفات إلى الخادم

سؤال

السلام عليكم،

لا توجد طريقة في ال servlets تتيح لنا رفع الملفات، لذلك يجب علينا إما أن نكتبها بأنفسنا، وهذا ليس شيئا مستحيلا، لكنه صعب نوعا ما ومتعب، حيث يجب معرفة بنية ال HTTP request في حالة ال post method، ويجب قراءة هذه ال request لاستخراج الملف وبقية المحتوى.... :wacko:

وإما نستخدم مكتبة جاهزة توفر علينا الجهد والوقت.

في هذا المثال سنستعمل المكتبة commons.fileupload. هناك طبعا مكتبات أخرى تقوم بنفس العمل، لكن سنكتفي بهاته فقط.

اولا يجب تحميل المكتبة، من هنا. تقومون بفك الضغط عن الملف zip وتضيفون الملف commons-fileupload-1.2.1.jar إلى المشروع.

هذه المكتبة تعتمد على مكتبة أخرى هي commons.io، يمكن تحميلها من هنا، ثم تقومون بفك الضغط عن الملف zip وتضيفون الملف commons-io-1.4.jar إلى المشروع.

ملاحظة: الملفان jar مرفقان مع الموضوع.

الآن سنبدأ بكتابة ال servlet.

الكود الذي سنكتبه، سيكون موجودا في الطريقة doPost()، لأن رفع الملفات يتم عن طريق ال POST method، وليس GET method.

أولا، نسترجع كائن PrintWriter الذي سيتيح لنا الكتابة.

PrintWriter out = response.getWriter();

ثم نحدد نوع الصفحة التي سنعيدها

response.setContentType("text/html");

الآن، نسترجع كائن من فئة DiskFileItemFactory، هذا الكائن هو المسؤول عن تخزين الملفات التي يتم رفعها في الذاكرة، ريثما نخزنها في القرص الصلب.

DiskFileItemFactory factory = new DiskFileItemFactory();

ثم ننشئ كائنا من فئة ServletFileUpload، ونمرر له الكائن DiskFileItemFactory الذي أنشأنا سابقا. هذه الفئة هي التي تقوم بقراءة ال POST request وتستخرج محتواها.

ServletFileUpload fileUpload = new ServletFileUpload(factory);

بعد ذلك سنستخرج محتوى الrequest باستعمال الطريقة parseRequest التي نمرر لها كائن من فئة HttpServletRequest الذي تم تمريره إلى الطريقة doPost()

List listItems = fileUpload.parseRequest(request);

هذه الطريقة تعيد لنا لائحة تحتوي على كل مكونات ال POST request. فكما نعلم، عادة في صفحات الويب، الحقل الخاص باختيار الملف الذي سيتم رفعه يكون جزءا من form، ويكون معه حقول أخر يجب علينا ايضا استعادة قيمها، وهذا ما تقوم به الطريقة parseRequest. كل كائن في هذه اللائحة هو من الفئة FileItem.

الخطوة التالية هي قراءة عناصر اللائحة. بالنسبة لكل عنصر، سنقوم بالتحقق ما إذا كان حقلا عادية normal form field، أو حقلا خاصا برفع الملفات، وذلك عن طريق الطريقة isFormField() الخاصة ب FileItem.

for (Object o : listItems) {
FileItem fileItem = (FileItem)o;
if (fileItem.isFormField()) {
out.print(fileItem.getFieldName() + ": " + fileItem.getString());
} else {
fileItem.write(new File(getServletContext().getRealPath("/") + "/" + fileItem.getName()));
out.print("file uploaded successfully.");
}
}

في الكود السابق، نقوم ب loop على اللائحة، ونسترجع كل عنصر داخلها، إذا كان حقلا عاديا، أي أن isFormField() تعيد true، نقوم فقط بكتابة إسمه وقيمته، أما إذا كان حقلا خاصا بالملفات، فنقوم بتخزين الملف في المجلد الخاص بال web application، وذلك باستعمال الطريقة write الخاصة ب FileItem.

كود ال servlet

import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;

public class UploadServlet extends HttpServlet {


@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
PrintWriter out = response.getWriter();
response.setContentType("text/html");
DiskFileItemFactory factory = new DiskFileItemFactory();
ServletFileUpload fileUpload = new ServletFileUpload(factory);
try {
List listItems = fileUpload.parseRequest(request);
for (Object o : listItems) {
FileItem fileItem = (FileItem)o;
if (fileItem.isFormField()) {
out.print(fileItem.getFieldName() + ": " + fileItem.getString() + "<br/>");
} else {
fileItem.write(new File(getServletContext().getRealPath("/") + "/" + fileItem.getName()));
out.print("file uploaded successfully.");
}
}
} catch (FileUploadException ex) {
out.print("An error occured while processing the request: " + ex.getMessage());
} catch (Exception ex) {
out.print("An error occured while writing the uploaded file: " + ex.getMessage());
}
}
}

الآن سنكتب الصفحة HTML التي ستنادي على ال servlet

<html>
<head>
<title>Upload page</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>
<body>
<h1>Upload files using commons.fileupload library</h1>
<form action="/UploadFiles/UploadServlet" method="post" enctype="multipart/form-data">
Name: <input type="text" name="Name"/><br/>
Age: <input type="text" name="Age"/><br/>
Choose the file to upload: <input type="file" name="fileToUpload" /><br/>
<input type="submit"/>
</form>
</body>
</html>

أهم سطر في الكود السابق هو هذا السطر الخاص بالوسم form

<form action="/UploadFiles/UploadServlet" method="post" enctype="multipart/form-data">

أولا قمنا بتحديد الخاصية action وأعطيناها عنوان ال servlet التي كتبنا

ثم حددنا الmethod في post، وهذا ضروري عند رفع الملفات، لأن ال get method لا يمكن رفع الملفات عن طريقها.

وأخيرا حددنا قيمة المعطى enctype في multipart/form-data. عندما يكون لدينا form لرفع الملفات، يجب أن نحدد هذا المعطى ونعطيه هاته القيمة.

هذه القيم التي يمكننا تمريرها ل enctype

application/x-www-form-urlencoded= All characters are encoded before sent (this is default)

multipart/form-data= No characters are encoded. This value is required when you are using forms that have a file upload control

text/plain= Spaces are converted to "+" symbols, but no special characters are encoded

commons-io-1.4.jar

commons-fileupload-1.2.1.jar

UploadFiles_netbeans.zip

UploadFiles.war.zip

تم تعديل بواسطه herch
2

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

7 إجابة على هذا السؤال .

  • 0

السلام عليكم

بأمانة عمل رائع

يبدو لي أنك انتقلت إلى J2EE وبقوة :)

تحياتي

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

شكرا :)

هي المطلوبة في سوق الشغل حاليا :wink:، لذلك أحاول تعلمها.

تم تعديل بواسطه herch
0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

بالتوفيق إن شاء الله

تحياتي

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

السلام عليكم

اخي الكريم herch

احييك علي الشرح الرائع الذي استفدت منه كثيرا و انا كان عندي سؤال بخصوص المثال اللي حضرتك شرحته

بخصوص سطر الكود


fileItem.write(new File(getServletContext().getRealPath("/") + "/" + fileItem.getName()));

علي حسب علمي ان هذا السطر يقوم بكتابة الملف المراد رفعه في ال physical path الخاص بالسيرفر اي كان نوع السيرفر

و عند تجربة الكود لاحظت ان الملف يتم حفظة في المسار التالي


C:\Documents and Settings\elbarody\Application Data\JDeveloper\system11.1.1.5.37.60.13\o.j2ee\drs\UploadFiles\UploadFilesWebApp.war\m.jpg

ولا يتم حفظة مثلا في ملف ال image اللي موجود تحت context root

و قد علمت السبب ان ملف war في حالة ال deploy بيكون من النوع read only و لهذا فلا يمكن الكتابة داخل هذا الملف او التعديل فيه

و لكن واجهتني مشكله و هي موضوع سؤالي لك ...

في حالة لو قمت بعمل deploy مرة اخري للسيرفر فان الملفات التي قمت بعمل رفع لها قد حذفت :sad:

خصوصا لو قد كنت عمل تخزين لمسار هذه الملفات في قاعدة البيانات فان سيكون من الصعب استدعاء هذه الملفات مرة اخري سواء بعملية download او بعرض الصور المخزنة مثلا في gallary

فهل يوجد طريقة اخري تمكنني من تخزين الملفات في مسار ثابت اخر ؟؟؟

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

يمكنك تغيير المسار إلى مسار بعيد عن الخادم

ابدا مثلاً بـ d:\blabla\bla\file.bla

تحياتي

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

عندي سؤال لو اردت تحديد نوع الملف يعني

اريد ان ارفع الصور الي من نوع .jpg و .png فقط!

كيف يتم هذا ؟

مشكورين على الجهد الرائع :)

تم تعديل بواسطه عاشق الكون
0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

بالنسبة لتعليق البارودي. كلامك صحيح

لكن في السيرفر يوجد مجلد معين لا يحضرني اسمه حاليا تستطيع رفع ملفاتك فيه.

كما انه يختلف اسم المجلد من سيرفر لاخر.

الاكيد اني سبق ورفعت ملفات علي سيرفر tomcat

شكرا عزيزي عصام علي هذا الشرح... درس مميز كعادتك

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

من فضلك سجل دخول لتتمكن من التعليق

ستتمكن من اضافه تعليقات بعد التسجيل



سجل دخولك الان

  • يستعرض القسم حالياً   0 members

    لا يوجد أعضاء مسجلين يشاهدون هذه الصفحة .