For file upload, browsers submit files as streams to the server in the process of uploading. If it is more troublesome to get the input stream of uploaded files directly by using Servlet and then parse the request parameters, it is generally preferred to use apache's open source tool common-fileupload as the file upload component. The jar package of the common-fileupload upload component can be downloaded on apache's official website or found under the lib folder of struts. The function of struts upload is based on this. Comm-fileupload relies on the common-io package, so it needs to be downloaded.
1. Construction of Development Environment
Create a FileUpload AndDownLoad project and join Apache's commons-fileupload file upload component's Jar package (note to put it under WebRoot-WEB-INF-lib, not build path), as shown below:
2. Implementing file upload
2.1. File upload page and message prompt page
The code for upload.jsp page is as follows:
<%@ page language="java" pageEncoding="UTF-8"%> <!DOCTYPE HTML> <html> <head> <title>File upload</title> </head> <body> <form action="${pageContext.request.contextPath}/servlet/UploadHandleServlet" enctype="multipart/form-data" method="post"> //Upload user: <input type="text" name="username"><br/> //Upload file 1: <input type="file" name="file1"><br/> //Upload file 2: <input type="file" name="file2"><br/> <input type="submit" value="Submission"> </form> </body> </html>
The code for message.jsp is as follows:
<%@ page language="java" pageEncoding="UTF-8"%> <!DOCTYPE HTML> <html> <head> <title>Message hint</title> </head> <body> ${message} </body> </html>
2.2. Servlet Processing File Upload
The code for the Upload Handle Servlet is as follows:
package me.gacl.web.controller; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; 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 UploadHandleServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //Get the saved directory of uploaded files, store the uploaded files in WEB-INF directory, do not allow outside direct access, ensure the security of uploaded files. String savePath = this.getServletContext().getRealPath("/WEB-INF/upload"); File file = new File(savePath); //Determine whether the saved directory of the uploaded file exists if (!file.exists() && !file.isDirectory()) { System.out.println(savePath+"The directory does not exist and needs to be created"); //Create directory file.mkdir(); } //Message hint String message = ""; try{ //Processing file upload steps using Apache file upload component: //1. Create a DiskFile ItemFactory DiskFileItemFactory factory = new DiskFileItemFactory(); //2. Create a file upload parser ServletFileUpload upload = new ServletFileUpload(factory); //Resolve Chinese Scrambling of Uploaded File Names upload.setHeaderEncoding("UTF-8"); //3. Determine whether the submitted data is uploaded form data? if(!ServletFileUpload.isMultipartContent(request)){ //Obtaining data in a traditional way return; } //4. Using the ServletFileUpload parser to parse the uploaded data, the parsing result returns a List < FileItem > collection, each FileItem corresponds to an input item of a Form form. List<FileItem> list = upload.parseRequest(request); for(FileItem item : list){ //If the data encapsulated in fileitem is normal input item if(item.isFormField()){ String name = item.getFieldName(); //Solving the Chinese scrambling problem of the data of common input items String value = item.getString("UTF-8"); //value = new String(value.getBytes("iso8859-1"),"UTF-8"); System.out.println(name + "=" + value); }else{//If the uploaded file is encapsulated in fileitem //Get the name of the uploaded file. String filename = item.getName(); System.out.println(filename); if(filename==null || filename.trim().equals("")){ continue; } //Note: File names submitted by different browsers are different. Some browsers submit file names with paths, such as: c: a b 1.txt, while others are simply file names, such as: 1.txt. //Processing the path part of the file name of the acquired uploaded file, leaving only the file name part filename = filename.substring(filename.lastIndexOf("\\")+1); //Get the input stream of the uploaded file in item InputStream in = item.getInputStream(); //Create a file output stream FileOutputStream out = new FileOutputStream(savePath + "\\" + filename); //Create a buffer byte buffer[] = new byte[1024]; //Identification to determine whether the data in the input stream has been read out int len = 0; //The loop reads the input stream into the buffer, (len = in. read (buffer) > 0 means that there is data in the buffer. while((len=in.read(buffer))>0){ //Use the FileOutputStream output stream to write buffer data to the specified directory (savePath + "\" + filename) out.write(buffer, 0, len); } //Close the input stream in.close(); //Close the output stream out.close(); //Delete temporary files generated when processing file uploads item.delete(); message = "Document upload success!"; } } }catch (Exception e) { message= "File upload failed!"; e.printStackTrace(); } request.setAttribute("message",message); request.getRequestDispatcher("/message.jsp").forward(request, response); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
Register Upload Handle Servlet in Web.xml file
<servlet> <servlet-name>UploadHandleServlet</servlet-name> <servlet-class>me.gacl.web.controller.UploadHandleServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>UploadHandleServlet</servlet-name> <url-pattern>/servlet/UploadHandleServlet</url-pattern> </servlet-mapping>
The operation results are as follows:
After successful file upload, the upload file is saved in the upload directory of WEB-INF directory, as shown in the following figure:
2.3. Details of file upload
Although the above code can successfully upload files to the specified directory on the server, the file upload function has many small details to pay attention to. The following points need special attention
1. In order to ensure the security of the server, uploaded files should be placed in directories that can not be accessed directly by the outside world, such as WEB-INF directory.
2. To prevent file overwriting, a unique file name should be created for uploading files.
3. In order to prevent too many files from appearing under a directory, hash algorithm should be used to scatter the storage.
4. Limit the maximum value of uploaded files.
5. To limit the type of uploaded file, judge whether the suffix name is legal when the uploaded file name is received.
To address the five details mentioned above, let's improve the Upload Handle Servlet. The improved code is as follows:
package me.gacl.web.controller; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.util.List; import java.util.UUID; 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.FileUploadBase; import org.apache.commons.fileupload.ProgressListener; import org.apache.commons.fileupload.disk.DiskFileItemFactory; import org.apache.commons.fileupload.servlet.ServletFileUpload; /** * @ClassName: UploadHandleServlet * @Description: TODO(Here is a sentence describing the function of this class. * @author: Aloof and proud wolf * @date: 2015-1-3 11:35:50 p.m. * */ public class UploadHandleServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //Get the saved directory of uploaded files, store the uploaded files in WEB-INF directory, do not allow outside direct access, ensure the security of uploaded files. String savePath = this.getServletContext().getRealPath("/WEB-INF/upload"); //Temporary file saved directory generated when uploading String tempPath = this.getServletContext().getRealPath("/WEB-INF/temp"); File tmpFile = new File(tempPath); if (!tmpFile.exists()) { //Create temporary directories tmpFile.mkdir(); } //Message hint String message = ""; try{ //Processing file upload steps using Apache file upload component: //1. Create a DiskFile ItemFactory DiskFileItemFactory factory = new DiskFileItemFactory(); //Set the size of the factory buffer. When the uploaded file size exceeds the size of the buffer, a temporary file will be generated and stored in the specified temporary directory. factory.setSizeThreshold(1024*100);//Set the size of the buffer to 100KB. If not specified, the default size of the buffer is 10KB. //Set the save directory of temporary files generated when uploading factory.setRepository(tmpFile); //2. Create a file upload parser ServletFileUpload upload = new ServletFileUpload(factory); //Monitor file upload progress upload.setProgressListener(new ProgressListener(){ public void update(long pBytesRead, long pContentLength, int arg2) { System.out.println("The file size is:" + pContentLength + ",Currently processed:" + pBytesRead); /** * File size: 14608, currently processed: 4096 File size: 14608, currently processed: 7367 File size: 14608, currently processed: 11419 File size: 14608, currently processed: 14608 */ } }); //Resolve Chinese Scrambling of Uploaded File Names upload.setHeaderEncoding("UTF-8"); //3. Determine whether the submitted data is uploaded form data? if(!ServletFileUpload.isMultipartContent(request)){ //Obtaining data in a traditional way return; } //Set the maximum size for uploading a single file, currently set to 1024 * 1024 bytes, or 1MB upload.setFileSizeMax(1024*1024); //Set the maximum value of the total number of uploaded files, the maximum value = the sum of the maximum sizes of multiple files uploaded at the same time, currently set to 10MB upload.setSizeMax(1024*1024*10); //4. Using the ServletFileUpload parser to parse the uploaded data, the parsing result returns a List < FileItem > collection, each FileItem corresponds to an input item of a Form form. List<FileItem> list = upload.parseRequest(request); for(FileItem item : list){ //If the data encapsulated in fileitem is normal input item if(item.isFormField()){ String name = item.getFieldName(); //Solving the Chinese scrambling problem of the data of common input items String value = item.getString("UTF-8"); //value = new String(value.getBytes("iso8859-1"),"UTF-8"); System.out.println(name + "=" + value); }else{//If the uploaded file is encapsulated in fileitem //Get the name of the uploaded file. String filename = item.getName(); System.out.println(filename); if(filename==null || filename.trim().equals("")){ continue; } //Note: File names submitted by different browsers are different. Some browsers submit file names with paths, such as: c: a b 1.txt, while others are simply file names, such as: 1.txt. //Processing the path part of the file name of the acquired uploaded file, leaving only the file name part filename = filename.substring(filename.lastIndexOf("\\")+1); //Get the extension of the uploaded file String fileExtName = filename.substring(filename.lastIndexOf(".")+1); //If you need to limit the type of file you upload, you can use the extension of the file to determine whether the uploaded file type is legitimate. System.out.println("The extension of the uploaded file is:"+fileExtName); //Get the input stream of the uploaded file in item InputStream in = item.getInputStream(); //Get the name of the file saved String saveFilename = makeFileName(filename); //Get the saved directory of the file String realSavePath = makePath(saveFilename, savePath); //Create a file output stream FileOutputStream out = new FileOutputStream(realSavePath + "\\" + saveFilename); //Create a buffer byte buffer[] = new byte[1024]; //Identification to determine whether the data in the input stream has been read out int len = 0; //The loop reads the input stream into the buffer, (len = in. read (buffer) > 0 means that there is data in the buffer. while((len=in.read(buffer))>0){ //Use the FileOutputStream output stream to write buffer data to the specified directory (savePath + "\" + filename) out.write(buffer, 0, len); } //Close the input stream in.close(); //Close the output stream out.close(); //Delete temporary files generated when processing file uploads //item.delete(); message = "Document upload success!"; } } }catch (FileUploadBase.FileSizeLimitExceededException e) { e.printStackTrace(); request.setAttribute("message", "Single file exceeds maximum!!!"); request.getRequestDispatcher("/message.jsp").forward(request, response); return; }catch (FileUploadBase.SizeLimitExceededException e) { e.printStackTrace(); request.setAttribute("message", "The total size of uploaded files exceeds the maximum limit!!!"); request.getRequestDispatcher("/message.jsp").forward(request, response); return; }catch (Exception e) { message= "File upload failed!"; e.printStackTrace(); } request.setAttribute("message",message); request.getRequestDispatcher("/message.jsp").forward(request, response); } /** * @Method: makeFileName * @Description: Generate the file name of the uploaded file with the original name of uuid+""+file * @Anthor:Aloof and proud wolf * @param filename The original name of the file * @return uuid+"_"+The original name of the file */ private String makeFileName(String filename){ //2.jpg //To prevent file overwriting, a unique file name is generated for uploading files. return UUID.randomUUID().toString() + "_" + filename; } /** * To prevent too many files from appearing under a directory, hash algorithm is used to scatter storage. * @Method: makePath * @Description: * @Anthor:Aloof and proud wolf * * @param filename File name, to generate storage directory based on file name * @param savePath File Storage Path * @return New storage directory */ private String makePath(String filename,String savePath){ //Get the hashCode value of the file name, and get the address of the string object filename in memory. int hashcode = filename.hashCode(); int dir1 = hashcode&0xf; //0--15 int dir2 = (hashcode&0xf0)>>4; //0-15 //Construct a new saved directory String dir = savePath + "\\" + dir1 + "\\" + dir2; //upload\2\3 upload\3\5 //File can represent both files and directories File file = new File(dir); //If the directory does not exist if(!file.exists()){ //Create directory file.mkdirs(); } return dir; } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
III. File Download
3.1. List file resources for download
We want to provide file resources in Web application system for users to download. First of all, we need a page to list all files in the uploaded file directory. When users click on the file download hyperlink, we download the files and write a ListFile Servlet to list all downloaded files in Web application system.
The code for ListFileServlet is as follows:
package me.gacl.web.controller; import java.io.File; import java.io.IOException; import java.util.HashMap; import java.util.Map; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * @ClassName: ListFileServlet * @Description: List all downloaded files in the Web system * @author: Aloof and proud wolf * @date: 2015-1-4 9:54:40 p.m. * */ public class ListFileServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //Get the directory of the uploaded file String uploadFilePath = this.getServletContext().getRealPath("/WEB-INF/upload"); //Store the file name to download Map<String,String> fileNameMap = new HashMap<String,String>(); //Recursively traverse all files and directories in the filepath directory, and store the file name of the file in the map collection listfile(new File(uploadFilePath),fileNameMap);//File can represent either a file or a directory //Send the Map collection to the listfile.jsp page for display request.setAttribute("fileNameMap", fileNameMap); request.getRequestDispatcher("/listfile.jsp").forward(request, response); } /** * @Method: listfile * @Description: Recursively traverses all files in a specified directory * @Anthor:Aloof and proud wolf * @param file Represents both a file and a file directory. * @param map Map Collection for Storing File Names */ public void listfile(File file,Map<String,String> map){ //If the file represents not a file, but a directory if(!file.isFile()){ //List all files and directories in this directory File files[] = file.listFiles(); //Traverse files [] arrays for(File f : files){ //recursion listfile(f,map); } }else{ /** * Processing file names. Uploaded files are renamed in the form of uuid_file names, and the uuid_part of file names is removed. file.getName().indexOf("_")Retrieve the location of the first occurrence of the "" character in the string if the filename is similar to: 9349249849-88343-8344_A_Vanda.avi Then after file. getName (). substring (file. getName (). indexOf ("")+1) processing, you can get the Avanda. avi part. */ String realName = file.getName().substring(file.getName().indexOf("_")+1); //file.getName() gets the original name of the file, which is unique, so it can be used as a key. realName is the name after processing and may be repeated. map.put(file.getName(), realName); } } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
listfile method in ListFileServlet is used to list all files in the directory. Recursion is used in listfile method. In practice, we will create a table in the database, which will store the uploaded file name and the specific storage directory of the file. We can know the details of the file by querying the table. There is no need to use recursive operation to store directories. This example is because the database is not used to store the uploaded file names and the specific storage location of files, and the storage location of uploaded files is scattered by hashing algorithm. Therefore, recursion is needed. When recursion occurs, the obtained file names are stored in the Map set passed from outside to the file method. In this way, you can ensure that all files are stored in the same Map collection.
Configure ListFileServlet in Web.xml file
<servlet> <servlet-name>ListFileServlet</servlet-name> <servlet-class>me.gacl.web.controller.ListFileServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>ListFileServlet</servlet-name> <url-pattern>/servlet/ListFileServlet</url-pattern> </servlet-mapping>
The listfile.jsp page showing the download file is as follows:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <!DOCTYPE HTML> <html> <head> <title>Download File Display Page</title> </head> <body> <!-- ergodic Map aggregate --> <c:forEach var="me" items="${fileNameMap}"> <c:url value="/servlet/DownLoadServlet" var="downurl"> <c:param name="filename" value="${me.key}"></c:param> </c:url> ${me.value}<a href="${downurl}">download</a> <br/> </c:forEach> </body> </html>
Accessing the ListFileServlet, you can display the file resources provided for users to download in the listfile.jsp page, as shown in the following figure:
3.2. Realizing File Download
Write a Servlet for processing file downloads. The code for DownLoad Servlet is as follows:
package me.gacl.web.controller; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.OutputStream; import java.net.URLEncoder; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class DownLoadServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //Get the file name to download String fileName = request.getParameter("filename"); //23239283-92489-Avatar.avi fileName = new String(fileName.getBytes("iso8859-1"),"UTF-8"); //Uploaded files are stored in subdirectories in the / WEB-INF/upload directory String fileSaveRootPath=this.getServletContext().getRealPath("/WEB-INF/upload"); //Find the directory of the file by its name String path = findFileSavePathByFileName(fileName,fileSaveRootPath); //Get the file to download File file = new File(path + "\\" + fileName); //If the file does not exist if(!file.exists()){ request.setAttribute("message", "The resources you want to download have been deleted!!"); request.getRequestDispatcher("/message.jsp").forward(request, response); return; } //Processing File Names String realname = fileName.substring(fileName.indexOf("_")+1); //Set the response header to control the browser to download the file response.setHeader("content-disposition", "attachment;filename=" + URLEncoder.encode(realname, "UTF-8")); //Read the file to download and save it to the file input stream FileInputStream in = new FileInputStream(path + "\\" + fileName); //Create an output stream OutputStream out = response.getOutputStream(); //Creating Buffers byte buffer[] = new byte[1024]; int len = 0; //The loop reads the contents of the input stream into the buffer while((len=in.read(buffer))>0){ //Output Buffer Content to Browser to Realize File Download out.write(buffer, 0, len); } //Close File Input Stream in.close(); //Close the output stream out.close(); } /** * @Method: findFileSavePathByFileName * @Description: Find the path of the file to download through the file name and the root directory of the uploaded file * @Anthor:Aloof and proud wolf * @param filename File name to download * @param saveRootPath The root directory where the upload file is saved, that is, / WEB-INF/upload directory * @return Storage directory of files to download */ public String findFileSavePathByFileName(String filename,String saveRootPath){ int hashcode = filename.hashCode(); int dir1 = hashcode&0xf; //0--15 int dir2 = (hashcode&0xf0)>>4; //0-15 String dir = saveRootPath + "\\" + dir1 + "\\" + dir2; //upload\2\3 upload\3\5 File file = new File(dir); if(!file.exists()){ //Create directory file.mkdirs(); } return dir; } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
Configure DownLoadServlet in Web.xml file
<servlet> <servlet-name>DownLoadServlet</servlet-name> <servlet-class>me.gacl.web.controller.DownLoadServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>DownLoadServlet</servlet-name> <url-pattern>/servlet/DownLoadServlet</url-pattern> </servlet-mapping>
Click on the hyperlink and submit the request to DownLoad Servlet for processing. The file can be downloaded. The effect is as follows:
From the running results, we can see that our file download function can download files normally.
There's so much about file upload and download in Java Web.