In the Web application system development, the file upload and download function is very common function, today will talk about the JavaWeb file upload and download function.
For file uploading, the browser submits the file to the server in the form of stream during the upload process. It is troublesome to directly use the Servlet to obtain the input stream of the uploaded file and then parse the request parameters in it. Therefore, apache’s open source tool common-Fileupload is generally used to upload files. The common-fileupload upload jar can be downloaded from the Apache website or found in the Struts lib folder. Struts uploads are based on this implementation. Common-fileupload depends on the common-io package, so you need to download this package.
I. Construction of development environment
Create a FileUploadAndDownLoad project and add the jars for Apache’s commons-fileupload fileupload component, as shown below:
Two, to achieve file upload
2.1 File upload page and message prompt page
The code for the upload.jsp page is as follows:
<%@ page language="java" pageEncoding="UTF-8"%>
<! DOCTYPEHTML>
<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>
Copy the code
The code for message.jsp looks like this:
<%@ page language="java" pageEncoding="UTF-8"%>
<! DOCTYPEHTML>
<html>
<head>
<title>Message prompt</title>
</head>
<body>
${message}
</body>
</html>
Copy the code
2.2 servlets handling file uploads
Uploadhandle server vlet 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 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 {
// Obtain the directory for storing the uploaded files and store the uploaded files in the WEB-INF directory. Direct access is prohibited to ensure file security
String savePath = this.getServletContext().getRealPath("/WEB-INF/upload");
File file = new File(savePath);
// Check whether the directory for saving the uploaded file exists
if(! file.exists() && ! file.isDirectory()) { System.out.println(savePath+"Directory does not exist, needs to be created");
// Create directory
file.mkdir();
}
// Message prompt
String message = "";
try{
// Use the Apache file upload component to upload files.
// create a DiskFileItemFactory
DiskFileItemFactory factory = new DiskFileItemFactory();
// create a file upload parser
ServletFileUpload upload = new ServletFileUpload(factory);
// Resolve the garbled Chinese characters in the uploaded file name
upload.setHeaderEncoding("UTF-8");
//3. Determine whether the submitted data is the data of the uploaded form
if(! ServletFileUpload.isMultipartContent(request)){// Get data in the traditional way
return;
}
// Use the ServletFileUpload parser to parse the uploaded data and return a List
set. Each FileItem corresponds to an input item of the Form
List<FileItem> list = upload.parseRequest(request);
for(FileItem item : list){
// If fileItem encapsulates the data of ordinary input items
if(item.isFormField()){
String name = item.getFieldName();
// Solve the problem of garbled Chinese characters in the 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 fileItem encapsulates an uploaded file
// Get the name of the uploaded file,
String filename = item.getName();
System.out.println(filename);
if(filename==null || filename.trim().equals("")) {continue;
}
// Note: different browsers submit different file names. Some browsers submit file names with paths, such as c:\a\b\1.txt, while others submit simple file names, such as 1.txt
// Process the path part of the file name of the uploaded file, leaving only the file name part
filename = filename.substring(filename.lastIndexOf("\ \") +1);
// Get the input stream for 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];
// A flag to determine whether the data in the input stream has been read
int len = 0;
// Loop the input stream into the buffer, (len=in.read(buffer))>0 means there is data in
while((len=in.read(buffer))>0) {// Use FileOutputStream 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 while processing file uploads
item.delete();
message = "File uploaded successfully!"; }}}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); }}Copy the code
Register uploadHandle server in the 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>
Copy the code
The running effect is as follows:
After the file was successfully uploaded, the uploaded file was saved to the upload directory in the WEB-INF directory, as shown in the following figure:
2.3 Details of file uploading
While the above code successfully uploads files to the specified directory on the server, there are a number of minor details to pay attention to in the file upload function
1. To ensure server security, upload files to a directory that cannot be accessed directly, for example, the WEB-INF directory.
2. To prevent file overwriting, create a unique file name for the uploaded file.
3. To prevent too many files in a directory, use the hash algorithm to split the storage.
4. Limit the maximum number of uploaded files.
5, to limit the type of the uploaded file, when receiving the uploaded file name, determine whether the suffix is valid.
UploadHandleServlet UploadHandleServlet UploadHandleServlet UploadHandleServlet
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 one-sentence description of what this class does) *@author: Lone Wolf *@date: 2015-1-3 11:35:50 * */
public class UploadHandleServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// Obtain the directory for storing the uploaded files and store the uploaded files in the WEB-INF directory. Direct access is prohibited to ensure file security
String savePath = this.getServletContext().getRealPath("/WEB-INF/upload");
// Save directory for temporary files generated during upload
String tempPath = this.getServletContext().getRealPath("/WEB-INF/temp");
File tmpFile = new File(tempPath);
if(! tmpFile.exists()) {// Create a temporary directory
tmpFile.mkdir();
}
// Message prompt
String message = "";
try{
// Use the Apache file upload component to upload files.
// create a DiskFileItemFactory
DiskFileItemFactory factory = new DiskFileItemFactory();
// Set the size of the factory buffer. If the size of the uploaded file 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 default buffer size is 10KB
// Set the directory for saving temporary files generated during upload
factory.setRepository(tmpFile);
// 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("File size:" + 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 the garbled Chinese characters in the uploaded file name
upload.setHeaderEncoding("UTF-8");
//3. Determine whether the submitted data is the data of the uploaded form
if(! ServletFileUpload.isMultipartContent(request)){// Get data in the traditional way
return;
}
// Set the maximum size of a single file to be uploaded. Currently, the maximum size is 1024*1024 bytes, i.e. 1MB
upload.setFileSizeMax(1024*1024);
// set the maximum number of files to be uploaded. The maximum value is the sum of the maximum size of multiple files to be uploaded at the same time. The current value is 10MB
upload.setSizeMax(1024*1024*10);
// Use the ServletFileUpload parser to parse the uploaded data and return a List
set. Each FileItem corresponds to an input item of the Form
List<FileItem> list = upload.parseRequest(request);
for(FileItem item : list){
// If fileItem encapsulates the data of ordinary input items
if(item.isFormField()){
String name = item.getFieldName();
// Solve the problem of garbled Chinese characters in the 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 fileItem encapsulates an uploaded file
// Get the name of the uploaded file,
String filename = item.getName();
System.out.println(filename);
if(filename==null || filename.trim().equals("")) {continue;
}
// Note: different browsers submit different file names. Some browsers submit file names with paths, such as c:\a\b\1.txt, while others submit simple file names, such as 1.txt
// Process the path part of the file name of the 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 want to limit the type of files to be uploaded, you can use the file extension to determine whether the uploaded file type is valid
System.out.println("The extension of the uploaded file is:"+fileExtName);
// Get the input stream for the uploaded file in item
InputStream in = item.getInputStream();
// Get the name of the file to save
String saveFilename = makeFileName(filename);
// Get the directory to save 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];
// A flag to determine whether the data in the input stream has been read
int len = 0;
// Loop the input stream into the buffer, (len=in.read(buffer))>0 means there is data in
while((len=in.read(buffer))>0) {// Use FileOutputStream 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 while processing file uploads
//item.delete();
message = "File uploaded successfully!"; }}}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"."Total uploaded file size 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: Specifies the name of the file to be uploaded in the following format: uuid+"_"+ original file name *@Anthor: Lone Wolf *@paramFilename The original name of the file *@returnUuid +"_"+ the original file name */
private String makeFileName(String filename){ //2.jpg
// To prevent file overwriting, create a unique file name for the uploaded file
return UUID.randomUUID().toString() + "_" + filename;
}
/** * To prevent too many files under a directory, use the hash algorithm to break up the storage *@Method: makePath
* @Description:
* @AnthorLone Wolf * *@paramFilename specifies the filename, based on which a storage directory is generated@paramSavePath File storage path *@returnNew storage directory */
private String makePath(String filename,String savePath){
// Get the hashCode value of the filename, which is the memory address of the string object filename
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 be either a File or a directory
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); }}Copy the code
After improving the above mentioned 5 small details, our file upload function is relatively complete.
File download
3.1 list the file resources available for download
We want to provide the file resources in the Web application system for users to download. First of all, we want to have a page listing all the files under the directory of uploaded files. When the user clicks the hyperlink to download files, the download operation will be carried out.
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: Lists all downloaded files in the Web system *@author: Lone Wolf *@date: 2015-1-4 9:54:40 * */
public class ListFileServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// Get the directory to upload the file
String uploadFilePath = this.getServletContext().getRealPath("/WEB-INF/upload");
// Store the file name to download
Map<String,String> fileNameMap = new HashMap<String,String>();
// Recursively traverses all files and directories in the filepath directory, storing the file names into 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 the specified directory *@Anthor: Lone Wolf *@paramFile is a file and a file directory *@paramMap Map collection of file names */
public void listfile(File file,Map<String,String> map){
// If file is not a file, but a directory
if(! file.isFile()){// Lists all files and directories under this directory
File files[] = file.listFiles();
// Iterate through the files[] array
for(File f : files){
/ / recursionlistfile(f,map); }}else{
IndexOf ("_") retrieves the position in the string where the "_" character first appears if the filename is similar to: Avi file file.getName().substring(file.getName().indexof ("_")+1) */
String realName = file.getName().substring(file.getName().indexOf("_") +1);
//file.getName() returns the original name of the file. This name is unique and therefore can be used as the key. RealName is the processed name and may be duplicatedmap.put(file.getName(), realName); }}public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException { doGet(request, response); }}Copy the code
The listFile method is used to list all files in the directory. The listFile method uses recursion internally. In the actual development, we will definitely create a table in the database. Will be stored inside the upload file name and file storage directory, we can know the specific file through the query table storage directory, is not to need to use recursive operations, this example because no upload using a database to store the file name and file location, and upload file location using the hash algorithm scattered storage, So recursion is needed, and in recursion, the obtained file name is stored in the Map set passed to the listFile method, so that all files are stored in the same Map set.
Configure the ListFileServlet in the 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>
Copy the code
The listfile.jsp page showing the downloaded file looks like this:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<! DOCTYPEHTML>
<html>
<head>
<title>Download file display page</title>
</head>
<body>
<! 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>
Copy the code
To access the ListFileServlet, the listfile.jsp page displays the file resources provided to the user for download, as shown below:
3.2. Download files
Write a Servlet to handle file downloads. The code for 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 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");
// Uploads are stored in subdirectories under the/web-INF /upload directory
String fileSaveRootPath=this.getServletContext().getRealPath("/WEB-INF/upload");
// Find the directory where the file is located
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 resource you want to download has been deleted!!");
request.getRequestDispatcher("/message.jsp").forward(request, response);
return;
}
// Process the 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 download and save it to the file input stream
FileInputStream in = new FileInputStream(path + "\ \" + fileName);
// Create an output stream
OutputStream out = response.getOutputStream();
// Create buffer
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) {// Outputs the contents of the buffer to the browser for 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 you want to download by referring to the file name and the root directory of the uploaded file@Anthor: Lone Wolf *@paramFilename filename to download *@paramSaveRootPath = / web-INF /upload *@returnThe directory where the files to be downloaded are stored */
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); }}Copy the code
Configure the DownLoadServlet in the 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>
Copy the code
Click the hyperlink [Download], submit the request to DownLoadServlet for processing, and you can download the file. The running effect is as shown in the picture below:
It can be seen from the running result that our file download function can download files normally.
So much for the file upload and download capabilities in JavaWeb.
From: www.cnblogs.com/xdp-gacl/p/…