In the development of web application system, file upload and download functions are very commonly used functions. Today, let’s talk about the implementation of file upload and download functions in JavaWeb.
For file upload, the browser submits the file to the server in the form of a stream during the upload process. It is more troublesome if you directly use Servlet to obtain the input stream of the uploaded file and then parse the request parameters in it. Therefore, it is generally chosen to use the common-fileupload, the file upload component of the apache open source tool. The jar package of the common-fileupload upload component can be downloaded on the apache official website, or it can be found under the lib folder of struts. The function of struts upload is based on this implementation. common-fileupload depends on the common-io package, so you also need to download this package.
1. Development environment construction
Create a FileUploadAndDownLoad project and add Apache's commons-fileupload file upload component's related Jar package, as shown in the figure below:
2. Implement file upload
2.1. File upload page and message prompt page
The code of the 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="submit"> </form> </body> </html> The code for message.jsp is as follows: [html] view plain copy print?<%@ page language="java" pageEncoding="UTF-8"%> <!DOCTYPE HTML> <html> <head> <title>Message prompt</title> </head> <body> ${message} </body> </html>2.2. Processing Servlets for file uploads
The code of UploadHandleServlet 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 the uploaded file, store the uploaded file in the WEB-INF directory, and does not allow direct access from the outside world to ensure the security of the uploaded file String savePath = this.getServletContext().getRealPath("/WEB-INF/upload"); File file = new File(savePath); //Judge whether the saved directory of the uploaded file exists if (!file.exists() && !file.isDirectory()) { System.out.println(savePath+"Directory does not exist, it needs to be created"); //Create the directory file.mkdir(); } //Message prompts String message = ""; try{ //Use the Apache file upload component to handle file upload steps: //1. Create a DiskFileItemFactory factory DiskFileItemFactory factory = new DiskFileItemFactory(); //2. Create a file upload parser ServletFileUpload upload = new ServletFileUpload(factory); //Solve the Chinese garbled upload.setHeaderEncoding("UTF-8"); //3. Determine whether the submitted data is the data of the upload form if(!ServletFileUpload.isMultipartContent(request)){ //Get data return in the traditional way; } //4. Use the ServletFileUpload parser to parse the uploaded data. The parsing result returns a List<FileItem> collection. Each FileItem corresponds to the input item of a Form form List<FileItem> list = upload.parseRequest(request); for(FileItem item : list){ //If the data of a normal input item is encapsulated in the fileitem if(item.isFormField()){ String name = item.getFieldName(); //Solve the Chinese garbled problem of data of ordinary 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 file item encapsulates the uploaded file//get the uploaded file name, String filename = item.getName(); System.out.println(filename); if(filename==null || filename.trim().equals("")){ continue; } //Note: The file names submitted by different browsers are different. Some browsers submit files with paths, such as: c:/a/b/1.txt, and some are just simple file names, such as: 1.txt // Process the path part of the file name of the obtained uploaded file, only the file name part is retained filename = filename.substring(filename.lastIndexOf("//")+1); // Get the input stream of the uploaded file in the item InputStream in = item.getInputStream(); // Create a file output stream FileOutputStream out = new FileOutputStream(savePath + "//" + filename); // Create a buffer byte buffer[] = new byte[1024]; //The identification of whether the data in the input stream has been read is int len = 0; //The input stream is read into the buffer loop, (len=in.read(buffer))>0 means that there is still data in in while((len=in.read(buffer))>0){ //Use FileOutputStream output stream to write the 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 the temporary file generated when processing file upload item.delete(); message = "File upload was successfully uploaded! "; } } } } 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 UploadHandleServlet 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 effect is as follows:
After the file is uploaded successfully, the uploaded file is saved in the upload directory under the WEB-INF directory, as shown in the figure below:
2.3. Details of file upload
Although the above code can successfully upload files to the specified directory on the server, there are many small details that need to be paid attention to in the file upload function. The following points should be paid special attention to.
1. To ensure the security of the server, upload files should be placed in a directory that cannot be directly accessed by the outside world, such as in the WEB-INF directory.
2. To prevent file overwriting, a unique file name must be generated for uploading the file.
3. To prevent too many files from appearing under a directory, you must use the hash algorithm to break up the storage.
4. The maximum value of uploaded files should be limited.
5. To limit the type of uploaded files, when receiving the uploaded file name, determine whether the suffix name is legal.
In response to the above 5 detailed issues, let’s improve the UploadHandleServlet. 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 (I use one sentence to describe the function of this class) * @author: Guarantor* @date: 2015-1-3 11:35:50 pm * */ public class UploadHandleServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // Get the saved directory of the uploaded file, store the uploaded file in the WEB-INF directory, and does not allow direct access from the outside world to ensure the security of uploaded files String savePath = this.getServletContext().getRealPath("/WEB-INF/upload"); //The temporary file generated during upload is saved by the directory String tempPath = this.getServletContext().getRealPath("/WEB-INF/temp"); File tmpFile = new File(tempPath); if (!tmpFile.exists()) { //Create a temporary directory tmpFile.mkdir(); } //The message prompts String message = ""; try{ //Use the Apache file upload component to handle file upload steps: //1. Create a DiskFileItemFactory factory DiskFileItemFactory factory = new DiskFileItemFactory(); //Set the size of the factory's 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 buffer size to 100KB. If not specified, the buffer size is 10KB by default. //Set the storage directory of the temporary file generated during uploading factory.setRepository(tmpFile); //2. Create a file upload parser ServletFileUpload upload = new ServletFileUpload(factory); // Listen to file upload progress upload.setProgressListener(new ProgressListener(){ public void update(long pBytesRead, long pContentLength, int arg2) { System.out.println("File size is: " + pContentLength + ", currently processed: " + pBytesRead); /** * File size is: 14608, currently processed: 4096 File size is: 14608, currently processed: 7367 File size is: 14608, currently processed: 11419 File size is: 14608, currently processed: 14608 */ } }); // Solve the Chinese garbled upload.setHeaderEncoding("UTF-8"); //3. Determine whether the submitted data is the data of the upload form if(!ServletFileUpload.isMultipartContent(request)){ //Get data return in the traditional way; } //Set the maximum value of the size of the uploaded single file, which is currently set to 1024*1024 bytes, that is, 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, which is currently set to 10MB upload.setSizeMax(1024*1024*10); //4. Use the ServletFileUpload parser to parse the uploaded data. The parsing result returns a List<FileItem> collection, each FileItem corresponds to the input item of a Form form List<FileItem> list = upload.parseRequest(request); for(FileItem item : list){ //If the fileitem encapsulates the data of ordinary input items if(item.isFormField()){ String name = item.getFieldName(); //Solves the Chinese garbled problem of data of ordinary 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 fileitem encapsulates the uploaded file//Get the uploaded file name, String filename = item.getName(); System.out.println(filename); if(filename==null || filename.trim().equals("")){ continue; } //Note: The file names submitted by different browsers are different. Some browsers submit file names with paths, such as: c:/a/b/1.txt, while some are just simple file names, such as: 1.txt // Process the path part of the file name of the obtained uploaded file, only the file name part is retained 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 uploaded file type, you can use the file extension to determine whether the uploaded file type is legal System.out.println("The extension of the uploaded file is: "+fileExtName); //Get the input stream of the uploaded file in the item InputStream in = item.getInputStream(); //Get the name of the file saved String saveFilename = makeFileName(filename); //Get the file save directory String realSavePath = makePath(saveFilename, savePath); //Create a file output stream FileOutputStream out = new FileOutputStream(realSavePath + "//" + saveFilename); //Create a buffer byte buffer[] = new byte[1024]; //The identification of determining whether the data in the input stream has been read is int len = 0; //The input stream is read into the buffer, (len=in.read(buffer))>0 means that there is still data in in while((len=in.read(buffer))>0){ //Use FileOutputStream output stream to write the 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 the temporary file generated when processing file upload //item.delete(); message = "File upload was successfully uploaded! "; } } } catch (FileUploadBase.FileSizeLimitExceededException e) { e.printStackTrace(); request.setAttribute("message", "The maximum value of a single file is exceeded!!!"); request.getRequestDispatcher("/message.jsp").forward(request, response); return; } catch (FileUploadBase.SizeLimitExceededException e) { e.printStackTrace(); request.setAttribute("message", "The total size of the uploaded file exceeds the maximum value of the 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 file name as: uuid+"_"+ the original name of the file* @Anthor:发官网* @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 must be generated for uploading the file. Return UUID.randomUUID().toString() + "_" + filename; } /** * To prevent too many files from appearing under a directory, you need to use the hash algorithm to break up the storage* @Method: makePath * @Description: * @Anthor: The lone and arrogant wolf* * @param filename The file name, generate the storage directory based on the 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 what you get is 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 save directory String dir = savePath + "//" + dir1 + "//" + dir2; //upload/2/3 upload/3/5 //File can represent both the file and the directory File file = new File(dir); //If the directory does not exist if(!file.exists()){ //Create the directory file.mkdirs(); } return dir; } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }After improving the above-mentioned five small details, our file upload function has been relatively complete.
3. File download
3.1. List the file resources provided to download
We want to provide the file resources in the web application system to users for download. First, we need to have a page to list all files in the uploaded file directory. When the user clicks on the file download hyperlink, it will be downloaded and write a ListFileServlet to list all downloaded files in the web application system.
The code of 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: Guarante* @date: 2015-1-4 9:54:40 pm * */ public class ListFileServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //Get the directory for uploading files String uploadFilePath = this.getServletContext().getRealPath("/WEB-INF/upload"); //Storing the file name to be downloaded 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 traverse all files in the specified directory* @Anthor:光克* @param file means a file, and also represents a file directory* @param map Map collection that stores 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 the directory File files[] = file.listFiles(); //Transfer files[] array for(File f : files){ //Recursive listfile(f,map); } }else{ /** * Process the file name. The uploaded file is renamed in the form of uuid_file name. Remove the uuid_ part of the file name file.getName().indexOf("_") to retrieve the location of the "_" character in the string. If the file name is similar to: 9349249849-88343-8344_A_Fan_Davi.avi, then file.getName().substring(file.getName().indexOf("_")+1) can get the A_Fan_Davi.avi part*/ String realName = file.getName().substring(file.getName().indexOf("_")+1); //file.getName() gets the original name of the file. This name is unique, so it can be used as a key. RealName is the processed name. It may be repeated map.put(file.getName(), realName); } } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } } Here I briefly talk about the listfile method in ListFileServlet. The listfile method is used to list all files in the directory. The listfile method uses recursion. In actual development, we will definitely 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 specific storage directory of the file by querying the table, and there is no need to use recursion operations. This example is because the database does not store the uploaded file name and the specific storage location of the file, and the storage location of the uploaded file is used to break up the storage, so recursion is needed. During recursion, the obtained file name is stored in the Map collection passed from outside to the listfile method, so we 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 displaying the downloaded 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> <!-- traverse Map collection--> <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> By accessing the ListFileServlet, you can display the file resources provided to users to download in the listfile.jsp page, as shown in the figure below:
3.2. Implement file download
Write a Servlet for processing file downloads. The code for the DownloadServlet 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 DownloadLoadServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //Get the file name to be downloaded String fileName = request.getParameter("filename"); //23239283-92489-Avatar.avi fileName = new String(fileName.getBytes("iso8859-1"),"UTF-8"); //The uploaded files are saved in the subdirectory of the /WEB-INF/upload directory String fileSaveRootPath=this.getServletContext().getRealPath("/WEB-INF/upload"); //Find out the directory where the file is located by the file name String path = findFileSavePathByFileName(fileName,fileSaveRootPath); //Get the file to be downloaded File file = new File(path + "//" + fileName); //If the file does not exist if(!file.exists()){ request.setAttribute("message", "The resource you want to download has been deleted!!"); request.getRequestDispatcher("/message.jsp").forward(request, response); return; } //Processing file name 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 be downloaded and save to the file input stream FileInputStream in = new FileInputStream(path + "//" + fileName); //Create the output stream OutputStream out = response.getOutputStream(); //Create the buffer byte buffer[] = new byte[1024]; int len = 0; //Loop read the content of the input stream into the buffer while((len=in.read(buffer))>0){ //Output the content of the buffer to the browser to realize the file download out.write(buffer, 0, len); } //Close the file input stream in.close(); //Close the output stream out.close(); } /** * @Method: findFileSavePathByFileName * @Description: Find the path of the file to be downloaded through the file name and storage root directory* @Anthor:发官网* @param filename The file name to be downloaded* @param saveRootPath The root directory for uploading the file, that is, /WEB-INF/upload directory* @return the storage directory of the file to be downloaded*/ 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); } }Configuring 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 the [Download] hyperlink, submit the request to the DownloadServlet and process it to achieve the file download. The operation effect is shown in the figure below:
From the running results, we can see that our file download function can download files normally.
The above is the most detailed explanation of the file upload and download examples introduced by the editor (recommended). I hope it will be helpful to everyone. If you have any questions, please leave me a message and the editor will reply to everyone in time. Thank you very much for your support to Wulin.com website!