Servlet Upload Bestand en Downloaden van Bestand is een veelvoorkomende taak in een Java webapplicatie. Aangezien ik de laatste tijd veel heb geschreven over Java Servlets, dacht ik eraan om een voorbeeld van het uploaden van een servletbestand naar de server en vervolgens het downloaden van de server naar de client te geven.
Servlet Bestand Uploaden
Ons gebruiksscenario is het aanbieden van een eenvoudige HTML-pagina waar de client een lokaal bestand kan selecteren om naar de server te uploaden. Bij het indienen van het verzoek om het bestand te uploaden, zal ons servletprogramma het bestand uploaden naar een map op de server en vervolgens de URL verstrekken waarmee de gebruiker het bestand kan downloaden. Om veiligheidsredenen wordt de gebruiker geen directe URL gegeven om het bestand te downloaden, maar ze krijgen een link om het bestand te downloaden en ons servlet zal het verzoek verwerken en het bestand naar de gebruiker sturen. We zullen een dynamisch webproject maken in Eclipse en de projectstructuur zal eruitzien als de onderstaande afbeelding. Laten we alle onderdelen van onze webapplicatie bekijken en de implementatie begrijpen.
Pagina voor het uploaden van bestanden naar de server
We kunnen een bestand naar de server uploaden door een postverzoek naar de servlet te sturen en het formulier in te dienen. We kunnen de GET-methode niet gebruiken voor het uploaden van een bestand. Een ander punt om op te merken is dat de enctype van het formulier moet zijn multipart/form-data. Om een bestand te selecteren uit het gebruikersbestandssysteem, moeten we het input-element gebruiken met type als file. Dus we kunnen een eenvoudige HTML-pagina index.html hebben voor het uploaden van een bestand als volgt:
<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>
Serverbestandslocatie voor het uploaden van bestanden
We moeten het bestand opslaan in een bepaalde directory op de server. We kunnen deze directory hardcoderen in het programma, maar voor een betere flexibiliteit zullen we deze configureerbaar houden in de contextparameters van het inzetingsdescriptor. Ook zullen we onze HTML-pagina voor het uploaden van bestanden toevoegen aan de lijst met welkomstbestanden. Ons web.xml-bestand zal er als volgt uitzien:
<?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 voor de locatie van het uploaden van bestanden
Aangezien we de contextparameter moeten lezen voor de bestandslocatie en er een `File`-object van moeten maken, kunnen we een `ServletContextListener` schrijven om dit te doen wanneer de context wordt geïnitialiseerd. We kunnen de absolute maplocatie en het `File`-object instellen als contextattribuut om te worden gebruikt door andere servlets. Onze implementatiecode van `ServletContextListener` ziet er als volgt uit.
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) {
// eventuele opruiming uitvoeren indien nodig
}
}
Servlet voor bestandsupload en -download
Update: Servlet Specs 3 heeft ondersteuning toegevoegd om bestanden op de server te uploaden in de API, dus we hoeven geen externe API te gebruiken. Bekijk alstublieft Servlet 3 Upload Bestand. Voor het uploaden van bestanden zullen we de Apache Commons FileUpload utility gebruiken. Voor ons project gebruiken we versie 1.3. FileUpload is afhankelijk van Apache Commons IO jar, dus we moeten beide in de lib-map van het project plaatsen, zoals u kunt zien in bovenstaande afbeelding voor de projectstructuur. We zullen de DiskFileItemFactory fabriek gebruiken die een methode biedt om het HttpServletRequest-object te analyseren en een lijst met FileItem terug te geven. FileItem biedt handige methoden om de bestandsnaam, veldnaam in het formulier, grootte en inhoudstype van het te uploaden bestand op te halen. Om een bestand naar een directory te schrijven, hoeven we alleen een File-object te maken en het als argument door te geven aan de write()-methode van FileItem. Aangezien het hele doel van de servlet is om een bestand te uploaden, zullen we de init()-methode overschrijven om het DiskFileItemFactory
-objectexemplaar van de servlet te initialiseren. We zullen dit object gebruiken in de implementatie van de doPost()-methode om het bestand naar de serverdirectory te uploaden. Zodra het bestand succesvol is geüpload, sturen we een respons naar de client met een URL om het bestand te downloaden. Aangezien HTML-links de GET-methode gebruiken, zullen we de parameter voor de bestandsnaam aan de URL toevoegen en dezelfde servlet doGet()-methode gebruiken om het downloadproces van het bestand te implementeren. Voor het implementeren van de servlet voor het downloaden van bestanden, openen we eerst de InputStream voor het bestand en gebruiken we de ServletContext.getMimeType()-methode om het MIME-type van het bestand te krijgen en dit in te stellen als het responscontenttype. We moeten ook de lengte van de inhoud van de respons instellen als de lengte van het bestand. Om ervoor te zorgen dat de client begrijpt dat we een bestand als respons verzenden, moeten we de header “Content-Disposition” instellen met de waarde “attachment; filename=“fileName”. Nadat we de responsconfiguratie hebben ingesteld, kunnen we de bestandsinhoud lezen vanuit InputStream en deze schrijven naar ServletOutputStream en de uitvoer naar de client flushen. Onze uiteindelijke implementatie van de UploadDownloadFileServlet ziet er als volgt uit.
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>");
}
}
De voorbeelduitvoering van het project wordt getoond in onderstaande afbeeldingen.
Download Servlet Bestand Uploaden Downloaden Project
Je kunt de Apache Commons IO jar en Apache Commons FileUpload jar downloaden vanaf onderstaande URL’s. https://commons.apache.org/proper/commons-fileupload/download_fileupload.cgi https://commons.apache.org/proper/commons-io/download_io.cgi
Download Servlet Bestand Uploaden Downloaden Voorbeeld Project
Bekijk het volgende artikel in de reeks over Servlet Exception Handling.
Source:
https://www.digitalocean.com/community/tutorials/servlet-upload-file-download-example