JavaEE component commons fileupload file upload download

  • 2020-05-10 18:10:41
  • OfStack

1. File upload overview

To realize the file upload function in Web development, there are two steps:

1. Add upload input item in 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 must be post
      2 , must be set encType Properties for  multipart/form-data. After setting this value, the browser will attach the file data when uploading the file http In the body of the request message, 
         And use MIME The protocol describes the uploaded files to facilitate the recipient to parse and process the uploaded data. 
      3 , must be set input the name Property, otherwise the browser will not send the data for the uploaded file. 
    -->

2. Read the file upload data in Servlet and save it to the server hard disk

The Request object provides an getInputStream method that reads the data submitted by the client. However, since users may upload multiple files at the same time, it is a very troublesome task to program the Servlet terminal to read the uploaded data directly and parse out the corresponding file data respectively.

For example, the following is part of the HTTP protocol for intercepted requests sent when a browser uploads a file:                


Accept-Language: zh-Hans-CN,zh-Hans;q=0.5
Content-Type: multipart/form-data; boundary=---------------------------7dfa01d1908a4
UA-CPU: AMD64
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/5.0 (Windows NT 6.2; Win64; x64; Trident/7.0; rv:11.0) like Gecko
Content-Length: 653
Host: localhost:8080
Connection: Keep-Alive
Pragma: no-cache
Cookie: JSESSIONID=11CEFF8E271AB62CE676B5A87B746B5F
-----------------------------7dfa01d1908a4
Content-Disposition: form-data; name="username"
zhangsan
-----------------------------7dfa01d1908a4
Content-Disposition: form-data; name="userpass"
1234
-----------------------------7dfa01d1908a4
Content-Disposition: form-data; name="filename1"; filename="C:\Users\ASUS\Desktop\upload.txt"
Content-Type: text/plain
this is first file content!
-----------------------------7dfa01d1908a4
Content-Disposition: form-data; name="filename1"; filename="C:\Users\ASUS\Desktop\upload2.txt"
Content-Type: text/plain
this is Second file content!
hello
-----------------------------7dfa01d1908a4--

As you can see from the data above, it is difficult to write a robust and stable program if you divide and read the data manually. So, for the convenience of the user process to upload data, Apache open-source organization provides 1 used to handle file upload forms 1 open source components (Commons - fileupload), the component performance is excellent, and its API extremely easy to use and allows developers to easily realize web file upload function, thus realize the file upload function in the web development, usually use Commons - fileupload component implementation.

  needs to import two jar packages: Commons-fileupload and commons-io


response.setContentType("text/html;charset=utf-8");// Set response encoding 
    request.setCharacterEncoding("utf-8");
    PrintWriter writer = response.getWriter();// Gets the response output stream 
    
    ServletInputStream inputStream = request.getInputStream();// Gets the request input stream 
    
    /*
     * 1 , create, DiskFileItemFactory Object to set the buffer size and temporary file directory 
     *   This class has two constructors 1 One is the construction method without parameters, 
     *   On the other 1 A is a constructor with two arguments 
     * @param int sizeThreshold, This parameter sets the size of the memory buffer and defaults to 10K . When the uploaded file is larger than the buffer size, fileupload The component will use the temporary file cache to upload the file 
     * @param java.io.File repository, This parameter specifies a temporary file directory with a default value of System.getProperty("java.io.tmpdir");
     * 
     *   If an argument - free constructor is used setSizeThreshold(int sizeThreshold),setRepository(java.io.File repository)
     *   Method to set it 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 , the use of DiskFileItemFactory Object creation ServletFileUpload Object and set the size of the uploaded file 
     *  
     *  ServletFileUpload Object is responsible for processing the uploaded file data and encapsulating each input item in the form 1 a FileItem
     *   Common methods for this object are: 
     *      boolean isMultipartContent(request); Determine whether the upload form is multipart/form-data type 
     *      List parseRequest(request); parsing request Object and put each in the form 1 The input items are wrapped into 1 a fileItem  Object and return 1 I saved all of them FileItem the list A collection of 
     *      void setFileSizeMax(long filesizeMax); Set the maximum value of a single uploaded file 
     *      void setSizeMax(long sizeMax); Set the maximum amount of uploaded wenjiang 
     *      void setHeaderEncoding(); Set the encoding format, to solve the problem of file name upload 
     */
    ServletFileUpload upload = new ServletFileUpload(factory);
    
    upload.setHeaderEncoding("utf-8");// Set the encoding format, to solve the problem of file name upload 
    /*
     * 3 , call ServletFileUpload.parseRequest Method resolution request object , get 1 Save all uploaded content List object 
     */
    List<FileItem> parseRequest=null;
    try {
       parseRequest = upload.parseRequest(request);
    } catch (FileUploadException e) {
      e.printStackTrace();
    }
    /*
     * 4 , list Do iterations, each iteration 1 a FileItem Object, calling it isFormField Method to determine if the file is uploaded 
     *  true The representation is a normal form field, called getFieldName , getString Method to get the field name and field value 
     *  false To upload a file, is called getInputStream Method to get the data input stream to read the uploaded data 
     *  
     *  FileItem Used to represent files in the upload form 1 Upload file objects or normal form objects 
     *   The common methods of this object are: 
     *     boolean isFormField(); judge FileItem is 1 File upload object or normal form object 
     *     true The representation is a normal form field, 
     *          The call getFieldName , getString Method to get the field name and field value 
     *     false To upload a file, 
     *          The call getName() Get the file name of the uploaded file. Note: some browsers carry the client path and need to subtract it themselves 
     *          call getInputStream() Method to get the data input stream to read the uploaded data 
     *         delete();  Means closed FileItem After the input stream, delete the temporary file. 
     */
    
    for (FileItem fileItem : parseRequest) {
      if (fileItem.isFormField()) {// Represents a common field 
        if ("username".equals(fileItem.getFieldName())) {
          String username = fileItem.getString();
          writer.write(" Your user name: "+username+"<br>");
        }
        if ("userpass".equals(fileItem.getFieldName())) {
          String userpass = fileItem.getString();
          writer.write(" Your password: "+userpass+"<br>");
        }
        
      }else {// The representation is the uploaded file 
        // Files uploaded by different browsers may have pathnames and need to be cut by themselves 
        String clientName = fileItem.getName();
        String filename = "";
        if (clientName.contains("\\")) {// If you include "\" Said is 1 A name with a path , Intercepts the last file name 
          filename = clientName.substring(clientName.lastIndexOf("\\")).substring(1);
        }else {
          filename = clientName;
        }
        
        UUID randomUUID = UUID.randomUUID();// generate 1 a 128 It's the only one in the world 1 logo 
        
        filename = randomUUID.toString()+filename;
        
        /*
         *  design 1 Three directory generation algorithms, if the total number of files used by the user to upload is in the order of a billion or more, are placed together 1 File indexing is very slow due to the number of directories down, 
         *  So, design 1 It is necessary and reasonable to have a directory structure to store files separately 
         *  will UUID Take the hash algorithm, hash it to a smaller scale, 
         *  will UUID the hashcode convert 1 a 8 bit 8 Base string, 
         *  From the first of this string 1 Bit start, each 1 Character representation 1 Level directory, and you're built 1 a 8 Level directory, each 1 Level directory at most 16 subdirectory 
         *  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);
        // Gets the absolute path to which folder to store the uploaded file 
        String filepath=request.getSession().getServletContext().getRealPath("upload");
        for (char c : hexUUID.toCharArray()) {
          filepath = filepath+"/"+c;
        }
        // If the directory does not exist, it is generated 8 Level directory 
        File filepathFile = new File(filepath);
        if (!filepathFile.exists()) {
          filepathFile.mkdirs();
        }
        // from Request The file is read from the input stream and written to the server 
        InputStream inputStream2 = fileItem.getInputStream();
        // Create the 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 upload files "+clientName+" successful <br>");
        // Close the resource 
        bos.close();
        inputStream2.close();
      }
    }
  // Pay attention to Eclipse The uploaded files are saved in the running directory of the project, not workspace In the project directory. 

  2. File uploadings need special attention: (these problems are all provided with simple solutions in the above code)

1. File storage location

To ensure the security of the server, the uploaded file should be saved in the WEB-INF directory of the application, or in a directory not managed by WEB server. If the user uploads a file with executable code, such as jsp file, he can do anything on the server side according to the mosaics access path.

2. In order to prevent multiple users from uploading files that resemble file names, which may lead to file overwriting, the file upload program shall ensure that the uploaded file has only one file name.

Rename the file name using the UUID + user upload method

About UUID:
UUID(Universally Unique Identifier) globally unique identifier is a number generated on a machine that is guaranteed to be unique to all machines in the same space and time. According to the standard calculations made by the open software foundation (OSF), Ethernet card addresses, nanosecond times, chip ID codes, and many possible Numbers are used. By the combination of the following sections: the current date and time (the first part of the UUID related to time, if you in generating a UUID, after a few seconds and generate a UUID, the first part, the rest of the same), the clock sequence, the global only 1 IEEE machine identification number (if there is a network card, from the network card, no card in other ways), UUID only 1 defect is that the generated results served longer.

It's a 128-bit number, usually in hexadecimal form. The core idea of the algorithm is to combine the network card of the machine, local time and one random number to generate GUID. In theory, if one machine produced 10 million GUID per second, it would be guaranteed (in a probabilistic sense) not to repeat for 3, 240 years.

Starting with JDK1.5, generating UUID becomes a simple matter of implementing UUID for JDK:

java.util.UUID, just call it directly.
UUID uuid   =   UUID.randomUUID();
String s = UUID. randomUUID (.) toString (); // id, the primary key used to generate the database, is very good.  
 
UUID is made up of a number of 106 digits, expressed in the form for example
550E8400-E29B-11D4-A716-446655440000  

3. In order to prevent too many files in a single directory from affecting the reading and writing speed of files, the program that processes the uploaded files should select the appropriate directory structure generation algorithm according to the possible total amount of uploaded files and store the uploaded files separately. For example, use the hashcode method to build a multilevel directory.

4. If different users have uploaded the same file, there is no need to store many copies of the same file on the server side, which is a waste of resources. Algorithm should be designed to solve the problem of duplicate files.

5. JSP technology automatically realizes multithreading. So developers don't need to think about the multithreaded operation of uploading files  

3. 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 characters in file names 
    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. Simplify file upload and download using the smartUpload component in SSH


Related articles: