السلام عليكم،
لا توجد طريقة في ال 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

