Exemple de téléchargement de fichier et de téléversement de fichier Servlet

Le téléchargement et le téléchargement de fichiers Servlet est une tâche courante dans l’application web java. Comme j’ai beaucoup écrit sur le servlet java récemment, j’ai pensé fournir un exemple de téléchargement de fichier servlet vers le serveur puis de téléchargement du serveur vers le client.

Téléchargement de fichier Servlet

Notre cas d’utilisation est de fournir une simple page HTML où le client peut sélectionner un fichier local à télécharger sur le serveur. Lors de la soumission de la demande de téléchargement du fichier, notre programme de servlet téléchargera le fichier dans un répertoire du serveur puis fournira l’URL par laquelle l’utilisateur peut télécharger le fichier. Pour des raisons de sécurité, l’utilisateur ne se verra pas fournir l’URL directe pour télécharger le fichier, mais on lui donnera un lien pour télécharger le fichier et notre servlet traitera la demande et enverra le fichier à l’utilisateur. Nous créerons un projet web dynamique dans Eclipse et la structure du projet ressemblera à l’image ci-dessous. Examinons tous les composants de notre application web et comprenons l’implémentation.

Page HTML pour le téléchargement de fichiers Java vers le serveur

Nous pouvons télécharger un fichier vers le serveur en envoyant une requête POST au servlet et en soumettant le formulaire. Nous ne pouvons pas utiliser la méthode GET pour télécharger un fichier. Un autre point à noter est que l’enctype du formulaire doit être multipart/form-data. Pour sélectionner un fichier à partir du système de fichiers de l’utilisateur, nous devons utiliser l’élément input avec type défini sur file. Ainsi, nous pouvons avoir une page HTML simple index.html pour le téléchargement de fichiers comme suit :

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

Emplacement du fichier sur le serveur pour le téléchargement de fichiers

Nous devons stocker le fichier dans un répertoire sur le serveur. Nous pouvons avoir ce répertoire codé en dur dans le programme, mais pour une meilleure flexibilité, nous le rendrons configurable dans les paramètres de contexte du descripteur de déploiement. De plus, nous ajouterons notre page HTML de téléchargement de fichiers à la liste des fichiers de bienvenue. Notre fichier web.xml ressemblera à ce qui suit :

<?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>ServletFileUploadDownloadExample</display-name>
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
  </welcome-file-list>
  <context-param>
    <param-name>tempfile.dir</param-name>
    <param-value>tmpfiles</param-value>
  </context-param>
</web-app>

ServletContextListener pour l’emplacement du téléchargement de fichiers

Étant donné que nous devons lire le paramètre de contexte pour l’emplacement du fichier et créer un objet File à partir de celui-ci, nous pouvons écrire un ServletContextListener pour le faire lorsque le contexte est initialisé. Nous pouvons définir l’emplacement du répertoire absolu et l’objet File en tant qu’attribut de contexte à utiliser par d’autres servlets. Notre code d’implémentation de ServletContextListener ressemble à ceci.

package com.journaldev.servlet;

import java.io.File;

import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;

@WebListener
public class FileLocationContextListener implements ServletContextListener {

    public void contextInitialized(ServletContextEvent servletContextEvent) {
    	String rootPath = System.getProperty("catalina.home");
    	ServletContext ctx = servletContextEvent.getServletContext();
    	String relativePath = ctx.getInitParameter("tempfile.dir");
    	File file = new File(rootPath + File.separator + relativePath);
    	if(!file.exists()) file.mkdirs();
    	System.out.println("File Directory created to be used for storing files");
    	ctx.setAttribute("FILES_DIR_FILE", file);
    	ctx.setAttribute("FILES_DIR", rootPath + File.separator + relativePath);
    }

	public void contextDestroyed(ServletContextEvent servletContextEvent) {
		// effectuer le nettoyage si nécessaire
	}
	
}

Serveur de téléchargement de fichiers

Mise à jour: La spécification Servlet 3 a ajouté la prise en charge du téléchargement de fichiers sur le serveur dans l’API, nous n’aurons donc pas besoin d’utiliser une API tierce. Veuillez consulter Téléchargement de fichier Servlet 3. Pour le téléchargement de fichiers, nous utiliserons l’utilitaire Apache Commons FileUpload, pour notre projet, nous utilisons la version 1.3. FileUpload dépend du fichier Apache Commons IO, nous devons donc placer les deux dans le répertoire lib du projet, comme vous pouvez le voir dans l’image ci-dessus de la structure du projet. Nous utiliserons la fabrique DiskFileItemFactory qui fournit une méthode pour analyser l’objet HttpServletRequest et renvoyer une liste de FileItem. FileItem fournit des méthodes utiles pour obtenir le nom du fichier, le nom du champ dans le formulaire, la taille et les détails du type de contenu du fichier à télécharger. Pour écrire le fichier dans un répertoire, tout ce que nous avons à faire est de créer un objet File et de le passer en argument à la méthode write() de FileItem. Puisque le but principal du servlet est de télécharger un fichier, nous remplacerons la méthode init() pour initialiser l’objet DiskFileItemFactory instance du servlet. Nous utiliserons cet objet dans l’implémentation de la méthode doPost() pour télécharger le fichier dans le répertoire du serveur. Une fois le fichier téléchargé avec succès, nous enverrons une réponse au client avec l’URL pour télécharger le fichier. Étant donné que les liens HTML utilisent la méthode GET, nous ajouterons le paramètre du nom de fichier dans l’URL et nous pourrons utiliser la même méthode doGet() du servlet pour mettre en œuvre le processus de téléchargement de fichier. Pour implémenter le servlet de téléchargement de fichier, nous ouvrirons d’abord l’InputStream pour le fichier et utiliserons la méthode ServletContext.getMimeType() pour obtenir le type MIME du fichier et le définir comme type de contenu de la réponse. Nous devrons également définir la longueur du contenu de la réponse comme la longueur du fichier. Pour nous assurer que le client comprend que nous envoyons un fichier en réponse, nous devons définir l’en-tête « Content-Disposition » avec la valeur « attachment; filename=“fileName”. Une fois que nous avons terminé de configurer la réponse, nous pouvons lire le contenu du fichier depuis l’InputStream et l’écrire dans ServletOutputStream, puis vider la sortie vers le client. Notre implémentation finale du servlet UploadDownloadFileServlet ressemble à ce qui suit.

package com.journaldev.servlet;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Iterator;
import java.util.List;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
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;

@WebServlet("/UploadDownloadFileServlet")
public class UploadDownloadFileServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
    private ServletFileUpload uploader = null;
	@Override
	public void init() throws ServletException{
		DiskFileItemFactory fileFactory = new DiskFileItemFactory();
		File filesDir = (File) getServletContext().getAttribute("FILES_DIR_FILE");
		fileFactory.setRepository(filesDir);
		this.uploader = new ServletFileUpload(fileFactory);
	}
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		String fileName = request.getParameter("fileName");
		if(fileName == null || fileName.equals("")){
			throw new ServletException("File Name can't be null or empty");
		}
		File file = new File(request.getServletContext().getAttribute("FILES_DIR")+File.separator+fileName);
		if(!file.exists()){
			throw new ServletException("File doesn't exists on server.");
		}
		System.out.println("File location on server::"+file.getAbsolutePath());
		ServletContext ctx = getServletContext();
		InputStream fis = new FileInputStream(file);
		String mimeType = ctx.getMimeType(file.getAbsolutePath());
		response.setContentType(mimeType != null? mimeType:"application/octet-stream");
		response.setContentLength((int) file.length());
		response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\"");
		
		ServletOutputStream os = response.getOutputStream();
		byte[] bufferData = new byte[1024];
		int read=0;
		while((read = fis.read(bufferData))!= -1){
			os.write(bufferData, 0, read);
		}
		os.flush();
		os.close();
		fis.close();
		System.out.println("File downloaded at client successfully");
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		if(!ServletFileUpload.isMultipartContent(request)){
			throw new ServletException("Content type is not multipart/form-data");
		}
		
		response.setContentType("text/html");
		PrintWriter out = response.getWriter();
		out.write("<html><head></head><body>");
		try {
			List<FileItem> fileItemsList = uploader.parseRequest(request);
			Iterator<FileItem> fileItemsIterator = fileItemsList.iterator();
			while(fileItemsIterator.hasNext()){
				FileItem fileItem = fileItemsIterator.next();
				System.out.println("FieldName="+fileItem.getFieldName());
				System.out.println("FileName="+fileItem.getName());
				System.out.println("ContentType="+fileItem.getContentType());
				System.out.println("Size in bytes="+fileItem.getSize());
				
				File file = new File(request.getServletContext().getAttribute("FILES_DIR")+File.separator+fileItem.getName());
				System.out.println("Absolute Path at server="+file.getAbsolutePath());
				fileItem.write(file);
				out.write("File "+fileItem.getName()+ " uploaded successfully.");
				out.write("<br>");
				out.write("<a href=\"UploadDownloadFileServlet?fileName="+fileItem.getName()+"\">Download "+fileItem.getName()+"</a>");
			}
		} catch (FileUploadException e) {
			out.write("Exception in uploading file.");
		} catch (Exception e) {
			out.write("Exception in uploading file.");
		}
		out.write("</body></html>");
	}

}

L’exécution d’échantillon du projet est présentée dans les images ci-dessous.

Télécharger le fichier Servlet File Upload Download Project

Vous pouvez télécharger le fichier Apache Commons IO jar et le fichier Apache Commons FileUpload jar depuis les URL ci-dessous. https://commons.apache.org/proper/commons-fileupload/download_fileupload.cgi https://commons.apache.org/proper/commons-io/download_io.cgi

Télécharger l’exemple de projet Servlet File Upload Download

Consultez le prochain article de la série sur la Gestion des exceptions Servlet.

Source:
https://www.digitalocean.com/community/tutorials/servlet-upload-file-download-example