تحميل ملف Servlet 3 – @MultipartConfig، جزء

اليوم سننظر في مثال رفع الملفات باستخدام تعليقة @MultipartConfig و javax.servlet.http.Part في Servlet 3. في وقت سابق، قمت بكتابة مقال حول رفع الملفات في سيرفلت واستخدمت واجهة برمجة التطبيقات Apache FileUpload ولكن هنا سنستخدم ميزة رفع الملفات في Servlet 3.

رفع الملفات في Servlet 3

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

MultipartConfig

نحتاج إلى تعليق واجهة معالجة رفع الملفات بتعليقة MultipartConfig للتعامل مع طلبات multipart/form-data المستخدمة لرفع الملف إلى الخادم. تحتوي تعليقة MultipartConfig على السمات التالية:

  • fileSizeThreshold: يمكننا تحديد عتبة الحجم التي بعدها سيتم كتابة الملف إلى القرص. قيمة الحجم معبرة بالبايت، لذا 1024*1024*10 تعني 10 ميجابايت.
  • الموقع: دليل حيث سيتم تخزين الملفات افتراضيًا، قيمته الافتراضية هي “”.
  • maxFileSize: الحد الأقصى لحجم الملف المسموح به للتحميل، قيمته مقدمة بالبايت. القيمة الافتراضية هي -1L مما يعني غير محدود.
  • maxRequestSize: الحد الأقصى لحجم الطلب multipart/form-data المسموح به. القيمة الافتراضية هي -1L مما يعني غير محدود.

اقرأ المزيد حول التعليقات في دليل تعليقات جافا.

واجهة الجزء

واجهة الجزء (interface) تمثل جزءًا أو عنصر نموذج تم استلامه في طلب POST multipart/form-data. بعض الأساليب المهمة هي getInputStream()، write(String fileName) التي يمكننا استخدامها لقراءة وكتابة الملف.

تغييرات HttpServletRequest

تمت إضافة طرق جديدة في HttpServletRequest للحصول على جميع الأجزاء في طلب multipart/form-data من خلال طريقة getParts(). يمكننا الحصول على جزء معين باستخدام الطريقة getPart(String partName). دعنا نرى مشروعًا بسيطًا حيث سنستخدم الطرق API أعلاه لتحميل الملف باستخدام السيرفلت. ستبدو هيكل مشروعنا كما في الصورة أدناه.

نموذج HTML

لدينا صفحة HTML بسيطة يمكننا من خلالها تحديد الملف للتحميل وإرسال الطلب إلى الخادم لتحميله. index.html

<html>
<head></head>
<body>
<form action="FileUploadServlet" method="post" enctype="multipart/form-data">
Select File to Upload:<input type="file" name="fileName">
<br>
<input type="submit" value="Upload">
</form>
</body>
</html>

سيرفلت تحميل الملف

إليك تنفيذ سيرفلت تحميل الملف الخاص بنا. FileUploadServlet.java

package com.journaldev.servlet;
 
import java.io.File;
import java.io.IOException;
 
import javax.servlet.ServletException;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;
 
@WebServlet("/FileUploadServlet")
@MultipartConfig(fileSizeThreshold=1024*1024*10, 	// 10 MB 
                 maxFileSize=1024*1024*50,      	// 50 MB
                 maxRequestSize=1024*1024*100)   	// 100 MB
public class FileUploadServlet extends HttpServlet {
 
    private static final long serialVersionUID = 205242440643911308L;
	
    /**
     * Directory where uploaded files will be saved, its relative to
     * the web application directory.
     */
    private static final String UPLOAD_DIR = "uploads";
     
    protected void doPost(HttpServletRequest request,
            HttpServletResponse response) throws ServletException, IOException {
        // يحصل على المسار المطلق لتطبيق الويب
        String applicationPath = request.getServletContext().getRealPath("");
        // ينشئ مسار الدليل لحفظ الملف المحمّل
        String uploadFilePath = applicationPath + File.separator + UPLOAD_DIR;
         
        // ينشئ الدليل للحفظ إذا لم يكن موجودًا
        File fileSaveDir = new File(uploadFilePath);
        if (!fileSaveDir.exists()) {
            fileSaveDir.mkdirs();
        }
        System.out.println("Upload File Directory="+fileSaveDir.getAbsolutePath());
        
        String fileName = null;
        // احصل على جميع الأجزاء من الطلب واكتبها إلى الملف على الخادم
        for (Part part : request.getParts()) {
            fileName = getFileName(part);
            part.write(uploadFilePath + File.separator + fileName);
        }
 
        request.setAttribute("message", fileName + " File uploaded successfully!");
        getServletContext().getRequestDispatcher("/response.jsp").forward(
                request, response);
    }
 
    /**
     * Utility method to get file name from HTTP header content-disposition
     */
    private String getFileName(Part part) {
        String contentDisp = part.getHeader("content-disposition");
        System.out.println("content-disposition header= "+contentDisp);
        String[] tokens = contentDisp.split(";");
        for (String token : tokens) {
            if (token.trim().startsWith("filename")) {
                return token.substring(token.indexOf("=") + 2, token.length()-1);
            }
        }
        return "";
    }
}

يرجى ملاحظة استخدام العلامة @MultipartConfig لتحديد معلمات الحجم المختلفة لتحميل الملف. نحتاج إلى استخدام سمة رأس الطلب “content-disposition” للحصول على اسم الملف الذي تم إرساله من العميل، سنقوم بحفظ الملف بنفس الاسم. موقع الدليل نسبي إلى تطبيق الويب حيث أقوم بحفظ الملف، يمكنك تكوينه إلى موقع آخر مثل في مثال Apache Commons FileUpload.

رد JSP

A simple JSP page that will be sent as response to client once the file is uploaded successfully to server. response.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" 
    "https://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Upload File Response</title>
</head>
<body>
	<%-- Using JSP EL to get message attribute value from request scope --%>
    <h2>${requestScope.message}</h2>
</body>
</html>

وصف النشر

لا يوجد شيء جديد في ملف web.xml لتحميل ملف سيرفلت، يُستخدم فقط لجعل index.html كملف ترحيب. web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xmlns="https://java.sun.com/xml/ns/javaee" xsi:schemaLocation="https://java.sun.com/xml/ns/javaee https://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0">
  <display-name>ServletFileUploadExample</display-name>
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
  </welcome-file-list>
</web-app>

الآن عند تشغيل التطبيق، نحصل على الصفحات التالية كاستجابة. ستظهر السجلات موقع الدليل حيث تم حفظ الملف ومعلومات رأس content-disposition.

Upload File Directory=/Users/pankaj/Documents/workspace/j2ee/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/wtpwebapps/ServletFileUploadExample/uploads
content-disposition header= form-data; name="fileName"; filename="IMG_2046.jpg"

I am running Tomcat through Eclipse, that’s why file location is like this. If you run tomcat through command line and deploy application by exporting as WAR file into webapps directory, you will get different structure but a clear one.

تنزيل مشروع تحميل ملفات Multipart Servlet 3

Source:
https://www.digitalocean.com/community/tutorials/servlet-3-file-upload-multipartconfig-part