تحميل وتنزيل ملفات JSP

⚡ ملخص ذكي

تُعدّ عمليتا تحميل وتنزيل الملفات في JSP من العمليات الأساسية لإدخال وإخراج البيانات، حيث تُمكّنان تطبيق الويب من استقبال الملفات من المستخدمين وإرسالها إليهم. يشرح هذا المورد كلا العمليتين باستخدام نماذج JSP، وApache Commons FileUpload، وفئات servlet، مع توفير شفرة برمجية كاملة قابلة للتنفيذ.

  • 📤 أساسيات التحميل: استخدم طريقة POST وقم بتعيين enctype إلى multipart/form-data لأي عملية تحميل ملف.
  • 🧩 أباتشي كومنز: تقوم DiskFileItemFactory و ServletFileUpload بتحليل طلب multipart إلى عناصر ملف.
  • 🗂️ معالجة السيرفلت: تقوم طريقة doPost بتكرار عناصر الملف وكتابة كل منها في مجلد الهدف.
  • 📥 مسار التنزيل: يقوم برنامج servlet ببث ملف باستخدام FileInputStream ورأس Content-Disposition.
  • ⚙️ ترتيب: يجب تحديد مسارات الملفات وحدود الحجم ونوع المحتوى قبل القراءة أو الكتابة.

تحميل وتنزيل ملفات JSP

تحميل ملف JSP

  • يمكننا تحميل أي ملفات باستخدام JSP.
  • يمكن أن يكون ملفًا نصيًا أو ملفًا ثنائيًا أو ملف صورة أو أي مستند آخر.
  • هنا في حالة تحميل الملف، سيتم استخدام طريقة POST فقط وليس طريقة GET.
  • يجب تعيين سمة Enctype على بيانات متعددة الأجزاء/النموذج.

مثال: استخدام الإجراء

في هذا المثال، نقوم بتحميل ملف باستخدام كائن الإدخال/الإخراج.

Action_file.jsp

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Guru File</title>
</head>
<body>
<a>Guru File Upload:</a>
Select file: <br />
<form action="action_file_upload.jsp" method="post"
                        enctype="multipart/form-data">
<input type="file" name="file" size="50" />
<br />
<input type="submit" value="Upload File" />
</form>
</body>
</html>

Action_file_upload.jsp

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<%@ page import="java.io.*,java.util.*, javax.servlet.*" %>
<%@ page import="javax.servlet.http.*" %>
<%@ page import="org.apache.commons.fileupload.*" %>
<%@ page import="org.apache.commons.fileupload.disk.*" %>
<%@ page import="org.apache.commons.fileupload.servlet.*" %>
<%@ page import="org.apache.commons.io.output.*" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Guru File Upload</title>
</head>
<body>
<%
   File file ;
   int maxFileSize = 5000 * 1024;
   int maxMemSize = 5000 * 1024;
   String filePath = "E:/guru99/data";

   String contentType = request.getContentType();
   if ((contentType.indexOf("multipart/form-data") >= 0)) {

      DiskFileItemFactory factory = new DiskFileItemFactory();
      factory.setSizeThreshold(maxMemSize);
      factory.setRepository(new File("c:\\temp"));
      ServletFileUpload upload = new ServletFileUpload(factory);
      upload.setSizeMax( maxFileSize );
      try{
         List fileItems = upload.parseRequest(request);
         Iterator i = fileItems.iterator();
         out.println("<html>");
         out.println("<body>");
         while ( i.hasNext () )
         {
            FileItem fi = (FileItem)i.next();
            if ( !fi.isFormField () )  {
                String fieldName = fi.getFieldName();
                String fileName = fi.getName();
                boolean isInMemory = fi.isInMemory();
                long sizeInBytes = fi.getSize();
                file = new File( filePath + "yourFileName") ;
                fi.write( file ) ;
                out.println("Uploaded Filename: " + filePath + fileName + "<br>");
            }
         }
         out.println("</body>");
         out.println("</html>");
      }catch(Exception ex) {
         System.out.println(ex);
      }
   }else{
      out.println("<html>");
      out.println("<body>");
      out.println("<p>No file uploaded</p>");
      out.println("</body>");
      out.println("</html>");
   }
%>
</body>
</html>

شرح الكود:

Action_file.jsp

Code السطر 12-18: هنا نقوم بإنشاء نموذج يحتوي على حقل ملف، والذي سيقوم بتحميل ملف إلى الخادم، وسيتم تمرير الإجراء إلى action_file_upload.jsp.

Action_file_upload.jsp

Code خط 20: هنا نقوم بتحديد مسار الملف إلى مسار معين.

Code السطر 23-38: هنا نتحقق مما إذا كان نوع المحتوى multipart/form-data. إذا كان كذلك، فإن المحتوى من نوع ملف، ويتم قراءته. بعد قراءة الملف، يُكتب في ملف مؤقت، ثم يُحوّل الملف المؤقت إلى الملف الرئيسي.

عند تنفيذ الكود أعلاه، ستحصل على الناتج التالي:

تحميل ملف JSP

الإخراج:

نقوم بتحميل ملف باستخدام خيار زر اختيار الملف، وسيقوم زر تحميل الملف بتحميل الملف إلى الخادم إلى المسار المقدم.

مثال: استخدام عمليات JSP

في هذا المثال، سنقوم بتحميل ملف باستخدام عمليات JSP. سنستخدم نموذجًا يحتوي على زر "تحميل"، وعند النقر على زر التحميل، سيتم تحميل الملف.

Uploading_1.jsp

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Guru Uploading File</title>
</head>
<body>
File: <br />
<form action="guru_upload" method="post"
                        enctype="multipart/form-data">
<input type="file" name="guru_file" size="50" />
<br />
<input type="submit" value="Upload" />
</form>
</body>
</html>

شرح الكود:

Code السطر 11-12: هنا نأخذ نموذجًا يتضمن إجراءً على خادم servlet المسمى guru_upload، والذي سيمر عبر طلب POST. كما أن السمة enctype تحدد كيفية ترميز بيانات النموذج وإرسالها إلى الخادم، وهي تُستخدم فقط مع طلب POST. هنا نضبطها على multipart/form-data، وهو ما ينطبق على الملف (نظرًا لكبر حجم البيانات).

Code خط 13: هنا نقوم بتحديد عنصر guru_file بنوع ملف ونعطي الحجم 50.

Code خط 15: هذا زر من نوع الإرسال يحمل اسم "تحميل"، والذي من خلاله سيتم استدعاء سيرفلت الإجراء وسيتم معالجة الطلب فيه، وسيتم قراءة الملف وكتابته في السيرفلت.

Guru_upload.java

package demotest;

import java.io.File;
import java.io.IOException;
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.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;

public class guru_upload extends HttpServlet {
	private static final long serialVersionUID = 1L;

    public guru_upload() {
        super();
        // TODO Auto-generated constructor stub
    }
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		        if(ServletFileUpload.isMultipartContent(request)){
		            try {
		                List <FileItem> multiparts = new ServletFileUpload(new DiskFileItemFactory()).parseRequest(request);
		                for(FileItem item : multiparts){
		                    if(!item.isFormField()){
		                        String name = new File(item.getName()).getName();
		                        item.write( new File("c:/guru/upload" + File.separator + name));
		                    }
		                }
		               //File uploaded successfully
		               request.setAttribute("gurumessage", "File Uploaded Successfully");
		            } catch (Exception ex) {
		               request.setAttribute("gurumessage", "File Upload Failed due to " + ex);
		            }
		        }else{

		            request.setAttribute("gurumessage","No File found");
 }
		        request.getRequestDispatcher("/result.jsp").forward(request, response);

		    }


}

شرح الكود:

Code السطر 12-14: هنا، سيتعين علينا استيراد مكتبة org.apache.commons إلى إعدادات الكود. كما سيتعين علينا استيراد فئة fileupload من مكتبة org.apache.commons.

Code خط 23: هنا لدينا طريقة doPost()، والتي سيتم استدعاؤها لأننا نمرر طريقة POST في JSP، وسوف تأخذ كائنات الطلب والاستجابة كمعاملات لها.

Code خط 26: هنا نقوم بإنشاء كائن من فئة ServletFileUpload من حزمة fileUpload التابعة لمكتبة org.apache.commons، والذي سيتحقق من وجود أي كائنات ملفات في JSP. إذا تم العثور على أي منها، فسيتم جلب هذه الكائنات من الطلب.

Code السطر 27-32: سنقوم بالمرور على عدد الملفات من خلال التحقق من عدد عناصر الملفات الموجودة في كائن multiparts، وهو كائن قائمة (في حال تحميل أكثر من ملف واحد)، ثم نحفظه في المجلد c:/guru/upload بالاسم المحدد. نكتب الملف باستخدام دالة الكتابة الخاصة بكائن الملف في المجلد المذكور.

Code خط 34: إذا لم يكن هناك استثناء، فإننا نقوم بتعيين سمة في الطلب باسم gurumessage بقيمة "تم تحميل الملف بنجاح".

Code السطر 35-36: في حالة حدوث استثناء، نقوم بتعيين رسالة تفيد بأن "تحميل الملف قد فشل".

Code خط 40: إذا لم يتم العثور على الملف، فسنقوم بتعيين الرسالة على أنها "لم يتم العثور على الملف".

Code خط 42: إعادة توجيه الطلب باستخدام كائن requestdispatcher إلى result.jsp مع كائنات الطلب والاستجابة.

نتيجة.jsp

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Guru Result</title>
</head>
<body>
<% String msg = (String)request.getAttribute("message");
   out.println(msg);
%>
</body>
</html>

شرح الكود:

Code خط 10: هنا نقوم باستخراج السمة من كائن الطلب بقيمة gurumessage إلى كائن سلسلة نصية.

Code خط 11: نحن هنا نطبع تلك الرسالة.

عندما ننفذ الكود أعلاه، نحصل على الإخراج التالي:

الإخراج:

تظهر لنا استمارة تحتوي على حقول لاختيار ملف من المجلد. بعد اختيار الملف، يجب النقر على زر التحميل.

تحميل الملفات باستخدام عمليات JSP

بمجرد النقر على زر التحميل، نتلقى رسالة تفيد بأنه تم تحميل الملف بنجاح.

تحميل الملفات باستخدام عمليات JSP

في الرسم التخطيطي أدناه، يمكننا أن نرى أن الملف قد تم تحميله إلى المجلد c:/guru/upload.

تحميل الملفات باستخدام عمليات JSP

تنزيل ملف JSP

في هذا المثال، سنقوم بتنزيل ملف من الدليل بالنقر فوق الزر.

جاري التحميل_1.jsp

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Downloading Guru Example</title>
</head>
<body>
Guru Downloading File<a href="guru_download">Download here!!!</a>
</body>
</html>

شرح الكود:

Code خط 10: لقد قدمنا ​​هنا رابطًا لتنزيل ملف من المجلد c:/guru/upload باستخدام servlet guru_download.

Guru_download.java

package demotest;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Servlet implementation class guru_download
 */
public class guru_download extends HttpServlet {
	private static final long serialVersionUID = 1L;

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		response.setContentType("text/html");
		PrintWriter out = response.getWriter();
		String gurufile = "test.txt";
		String gurupath = "c:/guru/upload/";
		response.setContentType("APPLICATION/OCTET-STREAM");
		response.setHeader("Content-Disposition", "attachment; filename=\""
				+ gurufile + "\"");

		FileInputStream fileInputStream = new FileInputStream(gurupath
				+ gurufile);

		int i;
		while ((i = fileInputStream.read()) != -1) {
			out.write(i);
		}
		fileInputStream.close();
		out.close();
	}


	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
	}

}

شرح الكود:

Code السطر 3-5: هنا نقوم باستيراد FileInputStream و IOException و PrintWriter من حزمة java.io.

Code خط 15: نحن بصدد تعريف guru_download بريمج الذي يمتد HttpServlet.

Code خط 18: بما أننا حددنا رابطًا، فسيتم تضمينه في URLلذلك سيتم معالجة طريقة GET (سيتم استدعاء doGet في servlet)، والتي تتضمن أيضًا كائنات الطلب والاستجابة.

Code السطر 19-20: نقوم بتحديد نوع المحتوى في كائن الاستجابة، كما نحصل على كائن الكاتب من الاستجابة.

Code السطر 21-22: تعريف متغير باسم gurufile بقيمة test.txt و gurupath كـ c:/guru/upload/.

Code السطر 23-25: نقوم بتعيين نوع المحتوى باستخدام كائن الاستجابة، ونستخدم طريقة setHeader، التي تقوم بتعيين العنوان في كائن الاستجابة كاسم الملف الذي تم تحميله.

Code السطر 27-28: نقوم بإنشاء FileInputStream حيث سنضيف gurupath+gurufile.

Code السطر 31-33: هنا اتخذنا أ حائط اللوب والذي سيستمر حتى تتم قراءة الملف، ولذلك وضعنا الشرط على أنه != -1. في هذا الشرط، نقوم بالكتابة باستخدام كائن الطباعة.

عند تنفيذ الكود أعلاه، ستحصل على المخرجات التالية:

الإخراج:

تحميل الملف

علينا النقر على ملف downloading_1.jsp، وسنحصل على رابط بعنوان "التحميل من هنا". عند النقر على هذا الرابط، سيتم تحميل الملف إلى النظام.

الأسئلة الشائعة

نعم. يمكن لمساعدي الذكاء الاصطناعي إنشاء نماذج Servlets وJSP لتحميل الملفات وتنزيلها، وإضافة منطق Apache Commons FileUpload، واقتراح عمليات التحقق. مع ذلك، يُنصح باختبار الكود ومراجعة مسارات الملفات وحدود أحجامها.

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

يقوم ترميز multipart/form-data بتقسيم الطلب إلى أجزاء بحيث تكون بيانات الملف الثنائي transmitملف ted سليم. بدونه، يرسل المتصفح اسم الملف فقط، وليس محتوى الملف الفعلي، إلى الخادم.

يُستخدم Apache Commons FileUpload، إلى جانب Commons IO، على نطاق واسع. فهو يحلل طلبات multipart، ويعرض كل عنصر FileItem، ويكتب المحتوى الذي تم تحميله إلى دليل محدد على الخادم.

تلخيص هذه التدوينة بـ: