1. File upload overview
To realize the file upload function in web development, two steps are required:
1. Add upload input items to the web page
<form action="#" method="post" enctype="multipart/form-data"> <input type="file" name="filename1"/><br> <input type="file" name="filename2"/><br> <input type="submit" value="upload"/> <form> <!-- 1. The form method must be post 2. The encType attribute must be multipart/form-data. After setting this value, when the browser uploads the file, it will attach the file data to the http request message body, and use the MIME protocol to describe the uploaded file to facilitate the receiver to parse and process the uploaded data. 3. The name attribute of input must be set, otherwise the browser will not send the uploaded file data. -->
2. Read file upload data in Servlet and save it to the server hard disk
The Request object provides a getInputStream method, through which data submitted by the client can be read. However, since users may upload multiple files at the same time, it is a very troublesome task to program and directly read the uploaded data on the Servlet side and parse the corresponding file data separately.
For example, the following is some of the contents of the HTTP protocol of the request sent by the intercepted browser when uploading the file:
Accept-Language: zh-Hans-CN,zh-Hans;q=0.5Content-Type: multipart/form-data; boundary=---------------------------7dfa01d1908a4UA-CPU: AMD64Accept-Encoding: gzip, deflateUser-Agent: Mozilla/5.0 (Windows NT 6.2; Win64; x64; Trident/7.0; rv:11.0) like GeckoContent-Length: 653Host: localhost:8080Connection: Keep-AlivePragma: no-cacheCookie: JSESSIONID=11CEFF8E271AB62CE676B5A87B746B5F-----------------------------7dfa01d1908a4Content-Disposition: form-data; name="username"zhangsan-----------------------------7dfa01d1908a4Content-Disposition: form-data; name="userpass"1234-----------------------------7dfa01d1908a4Content-Disposition: form-data; name="filename1"; filename="C:/Users/ASUS/Desktop/upload.txt"Content-Type: text/plainthis is first file content!-----------------------------7dfa01d1908a4Content-Disposition: form-data; name="filename1"; filename="C:/Users/ASUS/Desktop/upload2.txt"Content-Type: text/plainthis is Second file content!hello-----------------------------7dfa01d1908a4--
It can also be seen from the above data that it is difficult to write a robust and stable program if you manually divide and read the data. Therefore, to facilitate users to process upload data, Apache open source organization provides an open source component (Commons-fileupload) used to process form file uploads. This component has excellent performance and its API is extremely simple to use, which allows developers to easily implement the web file upload function. Therefore, in web development, the file upload function is usually implemented using the Commons-fileupload component.
Two jar packages need to be imported: Commons-fileupload, commons-io
response.setContentType("text/html;charset=utf-8");//Set response encoding request.setCharacterEncoding("utf-8"); PrintWriter writer = response.getWriter();//Get response output stream ServletInputStream inputStream = request.getInputStream();//Get request input stream/* * 1. Create a DiskFileItemFactory object, set the buffer size and temporary file directory* There are two constructors in this class, one is a constructor without parameters, and the other is a constructor with two parameters* @param int sizeThreshold, this parameter sets the size of the memory buffer, the default value is 10K. When the upload file is larger than the buffer size, the fileupload component will upload the file using the temporary file cache* @param java.io.File repository, this parameter specifies the temporary file directory, the default value is System.getProperty("java.io.tmpdir"); * * If a constructor without parameters is used, setSizeThreshold(int sizeThreshold), setRepository(java.io.File repository) * Method is set manually*/ DiskFileItemFactory factory = new DiskFileItemFactory(); int sizeThreshold=1024*1024; factory.setSizeThreshold(sizeThreshold); File repository = new File(request.getSession().getServletContext().getRealPath("temp"));// System.out.println(request.getSession().getServletContext().getRealPath("temp"));// System.out.println(request.getRealPath("temp")); factory.setRepository(repository); /* * 2. Use the DiskFileItemFactory object to create a ServletFileUpload object and set the size of the uploaded file* * The ServletFileUpload object is responsible for processing the uploaded file data and encapsulate each input item in the form into a FileItem * Common methods of this object are: * boolean isMultipartContent(request); determine whether the uploaded form is multipart/form-data type* List parseRequest(request); parse the request object, wrap each input item in the form into a fileItem object, and return a list collection that saves all FileItems* void setFileSizeMax(long filesizeMax); set the maximum value of a single uploaded file* void setSizeMax(long sizeMax); set the maximum value of the total amount of uploaded Wenjiang* void setHeaderEncoding(); set the encoding format to solve the problem of garbled code uploading file names*/ ServletFileUpload upload = new ServletFileUpload(factory); upload.setHeaderEncoding("utf-8");//Set the encoding format to solve the problem of garbled code uploading file names/* * 3. Call the ServletFileUpload.parseRequest method to parse the request object and get a List object that saves all uploaded content*/ List<FileItem> parseRequest=null; try { parseRequest = upload.parseRequest(request); } catch (FileUploadException e) { e.printStackTrace(); } /* * 4. Iterate over the list. Each iterate a FileItem object, call its isFormField method to determine whether it is a file upload* true means it is a normal form field, then call the getFieldName and getString methods to get the field name and field value * false is the upload file, and then call the getInputStream method to get the data input stream, thereby reading the upload data* * FileItem is used to represent an upload file object or an ordinary form object in the file upload form* The commonly used methods of this object are: * boolean isFormField(); determines whether FileItem is a file upload object or a normal form object * true means it is a normal form field, * then call getFieldName and getString methods to get the field name and field value * false as the upload file, * then call getName() to get the file name of the upload file. Note: Some browsers carry client paths and need to subtract themselves * Call getInputStream() method to get the data input stream, so as to read the upload data * delete(); means that after closing the FileItem input stream, delete temporary files are deleted. */ for (FileItem fileItem : parseRequest) { if (fileItem.isFormField()) {//Represents the normal field if ("username".equals(fileItem.getFieldName()))) { String username = fileItem.getString(); writer.write("Your username: "+username+"<br>"); } if ("userpass".equals(fileItem.getFieldName()))) { String userpass = fileItem.getString(); writer.write("Your password: "+userpass+"<br>"); } }else {// means an uploaded file//The files uploaded by different browsers may have a path name, and you need to cut String clientName = fileItem.getName(); String filename = ""; if (clientName.contains("//")) {//If "/" means a name with a path, the last file name is intercepted filename = clientName.substring(clientName.lastIndexOf("//")).substring(1); }else { filename = clientName; } UUID randomUUID = UUID.randomUUID();// Generate a 128-bit long globally unique identifier filename = randomUUID.toString()+filename; /* * Design a directory generation algorithm. If the total number of files uploaded by the user is orders of millions of orders of magnitude or more, putting them in the same directory causes the file index to be very slow. * Therefore, it is very necessary to design a directory structure to store files in a scattered manner, and reasonably * Convert the UUID hash algorithm to a smaller range, * Convert the hashcode of the UUID into an 8-bit eg octal string, * Starting from the first bit of this string, each character represents a first-level directory, so an eight-level directory is built, with up to 16 subdirectories in each level directory* This is a very efficient directory structure for both the server and the operating system*/ int hashUUID =randomUUID.hashCode(); String hexUUID = Integer.toHexString(hashUUID); //System.out.println(hexUUID); //Get the absolute path to which folder to store the uploaded file in String filepath=request.getSession().getServletContext().getRealPath("upload"); for (char c : hexUUID.toCharArray()) { filepath = filepath+"/"+c; } //If the directory does not exist, generate an eighth-level directory File filepathFile = new File(filepath); if (!filepathFile.exists()) { filepathFile.mkdirs(); } //Read the file from the Request input stream and write to the server InputStream inputStream2 = fileItem.getInputStream(); //Create a file on the server side File file = new File(filepath+"/"+filename); BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file)); byte[] buffer = new byte[10*1024]; int len = 0; while ((len= inputStream2.read(buffer, 0, 10*1024))!=-1) { bos.write(buffer, 0, len); } writer.write("You uploaded the file"+clientName+"successfully<br>"); //Close the resource bos.close(); inputStream2.close(); } } //Note that the uploaded file of Eclipse is saved in the project's running directory, not in the project directory in workspace.2. Issues that need special attention to file upload: (These problems are all provided with simple solutions in the above code)
1. Where to store files
To ensure the security of the server, the uploaded file should be saved in the WEB-INF directory of the application, or a directory not managed by the WEB server. If the user uploads a file with executable code, such as a jsp file, and accesses it according to the splicing access path, he can do anything on the server side.
2. In order to prevent multiple users from uploading files with the same file name, resulting in file overwriting, the file uploader should ensure that the uploaded file has a unique file name .
Rename using UUID + user upload filename
About UUID:
UUID (Universally Unique Identifier) globally unique identifier refers to the number generated on a machine, which ensures that it is unique to all machines in the same time and space. According to the standards set by the Open Software Foundation (OSF), Ethernet card address, nanosecond time, chip ID code and many possible numbers are used. It consists of the combination of the following parts: the current date and time (the first part of the UUID is related to time. If you generate another UUID a few seconds after generating a UUID, the first part is different, the rest is the same), the clock sequence, the globally unique IEEE machine identification number (if there is a network card, it is obtained from the network card, and no network card is obtained in other ways), the only disadvantage of UUID is that the result string generated will be relatively long.
It is a 128-bit long number, generally expressed in hexadecimal. The core idea of the algorithm is to generate a GUID in combination with the machine's network card, local time, and an instant number. Theoretically, if a machine generates 100,000 GUIDs per second, it can be guaranteed (in the sense of probability) that 3240 years will not be repeated.
Starting from JDK1.5, generating UUIDs has become a simple thing, thinking that JDK has implemented UUIDs:
java.util.UUID, just call it directly.
UUID uuid = UUID.randomUUID();
String s = UUID.randomUUID().toString();//The primary key id used to generate the database is very good. .
UUID is composed of a sixteen-digit number, which is expressed in the form of
550E8400-E29B-11D4-A716-446655440000
3. In order to prevent too many files in a single directory and affect the file reading and writing speed, the program that handles uploading files should choose the appropriate directory structure generation algorithm based on the total possible upload volume, and store the uploaded files in a dispersed manner. For example, use the hashcode method to build a multi-level directory.
4. If different users upload the same file, there is no need to store many copies of the same file on the server side. This is a waste of resources. An algorithm should be designed to solve the problem of duplicate files.
5. The JSP technology principle automatically implements multi-threading. Therefore, developers do not need to consider multi-threaded operations of uploading files
3. File download
<% ArrayList<String> fileNames = new ArrayList<String>(); fileNames.add("file/aa.txt"); fileNames.add("file/bb.jpg"); for(String fileName : fileNames) { %> <form action="DownloadServlet" method="get"> <input type="hidden" name="fileName" value="<%=fileName %>" /> <input type="submit" value="Download:<%=fileName %>" /> </form> <% } %> request.setCharacterEncoding("utf-8"); String filename = request.getParameter("fileName"); String urlname = URLEncoder.encode(filename, "utf-8");//Prevent Chinese garbled response.setHeader("Content-Disposition","attachment;filename="+urlname); FileInputStream fis = new FileInputStream(new File(request.getSession().getServletContext().getRealPath(filename))); BufferedInputStream bis = new BufferedInputStream(fis); ServletOutputStream sos = response.getOutputStream(); byte[] buffer = new byte[1024]; int len=0; while((len=bis.read(buffer, 0, 1024))!=-1){ sos.write(buffer, 0, len); } bis.close(); fis.close();4. Use the smartUpload component in SSH to simplify file upload and download
The above is all the content of this article. I hope it will be helpful to everyone's learning and I hope everyone will support Wulin.com more.