Detailed explanation of file upload in Java

Principle of file upload


If you want to go to a website, if you send a request or file download,

The computer is the client and the server is the s-side. There are websites, web applications and file operating system in the server

For IO flow, two pools may need a pipeline to wear things. The pipeline between two different computers is the network

There are protocols in the network. Protocols are for transmitting things

Transmitting files requires response headers and response bodies. If you want to transmit files or download files, we also need to set fixed response headers and response bodies

To upload a file, first enable the browser to support file upload input(file)

The input file is uploaded to the web application through the network, and then transferred from the web application to the file system

http 80

https 443

URL: refers to a specific address on the Internet

How to write NetWork transport?

Writing the network transmission project is very huge, so we directly use the existing java classes

Precautions for file upload

  1. In order to ensure the security of the server, the uploaded files should be placed in a directory that cannot be directly accessed by the outside world, such as the WEB-INF directory
  2. To prevent file overwriting, a unique file name (- timestamp UUID MD5 bit operation) should be generated for the uploaded file
  3. To limit the maximum number of uploaded files
  4. You can limit the type of uploaded file and judge whether the suffix is legal when you receive the uploaded file name

Classes needed to upload files

Required classes

ServletFileUpload is responsible for processing the uploaded file data and encapsulating each input item in the form into a FileItem object

The DiskFileItemFactory object is required when the ServletFileUpload object resolves the request. Therefore, we need to construct it before parsing

DiskFileItemFactory object, which sets the ServletFileUpload object through the construction method of ServletFileUpload object or setFileItemFactory() method

fileItemFactory property of

ServletFileUpload class

ServletFileUpload handles the uploaded file data, encapsulates each input item in the form into a FileItem object, and uses its parseRequest(HttpServletRequest) method

The data submitted through each HTML tag in the form can be encapsulated into a FileItem object, and then returned in the form of List. This method is simple and easy to use to handle uploaded files
The trim() method removes the leading and trailing spaces

Implementation process

The front end submits the form table, resulting in a file in the FileServlet

We implement the function of uploading files in FileServlet
1. First
Determine whether the uploaded file is an ordinary form or a form with a file

 if(!ServletFileUpload.isMultipartContent(request)){
            return;//Terminate the operation of the method, indicating that this is an ordinary form, which is returned directly
  }

2. Create a save path for the uploaded file. It is recommended that it be safe under the WEB-INF path. Users cannot directly access the uploaded file

 String uploadPath=this.getServletContext().getRealPath("/WEB-INF/upload");
        File uploadFile=new File(uploadPath);
        if(!uploadFile.exists()){
            uploadFile.mkdir();//Create this directory
        }
        System.out.println("Directory created successfully");

3. Cache, temporary file: if the file exceeds the specified size, it will be made into a temporary file, which will be automatically deleted in a few days, or remind the user to save it as permanent

String tmpPath=this.getServletContext().getRealPath("/WEB-INF/upload");
        File file=new File(tmpPath);
        if(!file.exists()){
            file.mkdir();//Create this directory
        }

4. The uploaded files generally need to be obtained through the stream. We can use request.getInputStream() to obtain the original file upload stream, which is very troublesome
However, we all recommend using Apache's file upload component, common fileUpload, which depends on the common IO component:
🌟 Create a DiskFileItemFactory object to handle the file upload path or size limit:
DiskFileItemFactory factory=new DiskFileItemFactory();
Set a buffer through this factory. When the uploaded file is larger than this buffer, put it into the temporary file:
factory.setSizeThreshold(1024*1024);
actory.setRepository(file);

DiskFileItemFactory factory=getDiskFileItemFactory(file);
//======================================================
DiskFileItemFactory getDiskFileItemFactory(File file){
        DiskFileItemFactory factory=new DiskFileItemFactory();
        //Set a buffer through this factory. When the uploaded file is larger than this buffer, put it into the temporary file:
        factory.setSizeThreshold(1024*1024);
        factory.setRepository(file);
        return factory;
    }

5. Get ServletFileload to listen
Monitor file upload progress

ServletFileUpload upload=getServletFileUpload(factory);
//=====================================================
ServletFileUpload getServletFileUpload(DiskFileItemFactory factory){
        ServletFileUpload upload=new ServletFileUpload(factory);
        //🌟 Monitor the progress of file upload
        upload.setProgressListener(new ProgressListener() {
            @Override
            //pBytesRead: read file size
            //pContentLength: file size
            public void update(long pBytesRead, long pContentLength, int pItems) {
                System.out.println("Total size:"+pContentLength+"Uploaded:"+pBytesRead);
            }
        });
        //Dealing with garbled code
        upload.setHeaderEncoding("UTF-8");
        //Sets the maximum value for a single file
        upload.setFileSizeMax(1024*1024*10);
        //Set the total size of files that can be uploaded
        //1024=1kb*1024=1M*10=10M
        upload.setSizeMax(1024*1024*10);
        return  upload;
    }

6. Process uploaded files

String msg=uploadParseRequest(upload,request,uploadPath);
//=======================================================
String uploadParseRequest(ServletFileUpload upload, HttpServletRequest request,String uploadPath){
        String msg="Upload failed";
        try {
            List<FileItem> fileItems=upload.parseRequest(request);
            //fileItem each form object
            for (FileItem fileItem : fileItems) {
                //Determine whether the uploaded file is an ordinary form or a form with a file
                if(fileItem.isFormField()){
                    //getFiledName refers to the name of the front-end form control;
                    String name=fileItem.getFieldName();
                    String value=fileItem.getString("UTF-8");
                    System.out.println(name+":"+value);
                }else{
                    //If it is a file form
                    //1. Processing documents=================
                    String uploadFileName=fileItem.getName();
                    System.out.println("Uploaded file name:"+uploadFileName);
                    //The file name may be illegal
                    if(uploadFileName.trim().equals("")||uploadFileName==null){
                        continue;
                    }
                    //Get the uploaded file name / images/gurl/paojie.png
                    String fileName=uploadFileName.substring(uploadFileName.lastIndexOf("/")+1);
                    //Get the suffix of the file
                    String fileExtName=uploadFileName.substring(uploadFileName.lastIndexOf(".")+1);
                    /*
                     * If the file suffix fileExtName is not what we want
                     * return and tell the user that the file type is wrong
                     * */
                    //You can use UUID (universal code for unique identification) to ensure that the file name is unique
                    //UUID.randomUUID() randomly generates a unique universal code
                    //Everything in network transmission needs to be serialized,
                    //POJO, entity classes can only be used locally. If you want to run on multiple computers, you need to serialize the objects when transmitting = = =
                    //implements Serializable does not have a method interface - "" tag interface. When the JVM virtual machine is running, the JVM's local method stack -- native - > C++
                    //JNI = Java Native Interface - > java localized interface
                    //Java stack
                    //UUID generates random sequence number through bit operation to ensure non repeatability
                    String uuidPath = UUID.randomUUID().toString();
                    //2. Storage address=================
                    //Where? uploadPath
                    //The real path of the file realPath
                    String realPath=uploadPath+"/"+uuidPath;
                    //Create a folder for each file
                    File realPathFile=new File(realPath);
                    if(!realPathFile.exists()){
                        realPathFile.mkdir();
                    }
                    //3. File transfer=================
                    //Get the stream of file upload
                    InputStream inputStream=fileItem.getInputStream();
                    //Create a file output stream
                    //realPath = real folder
                    //One file is missing, plus the name of the output file + "/" + uuidFileName
                    FileOutputStream fos=new FileOutputStream(realPath+"/"+fileName);
                    //Create a buffer
                    byte[] buffer=new byte[1024*1024];
                    //Judge whether the reading is completed
                    int len=0;
                    //If it is greater than 0, data still exists
                    while((len=inputStream.read(buffer))>0){
                        fos.write(buffer,0,len);
                    }
                    msg="Upload file succeeded";
                    //Close flow
                    fos.close();
                    inputStream.close();
                    fileItem.delete();//Upload the file successfully. Clear the temporary file

                }

            }
        } catch (FileUploadException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return  msg;
    }

7. Finally, the result of file upload is obtained and forwarded by Servlet request

 //servlet request forwarding message
        request.setAttribute("msg",msg);
        request.getRequestDispatcher("info.jsp").forward(request,response);

Complete code

package com.lding.servlet;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.ProgressListener;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;

import javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.util.List;
import java.util.UUID;

/**
 * @program: FileTransport
 * @description: ${description}
 * @author: Wang Ding
 * @date: 2021-11-11 11:25
 **/
public class FileServlet extends javax.servlet.http.HttpServlet {
    protected void doPost(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, IOException {
        System.out.println("get into FileServlet");
        //Determine whether the uploaded file is an ordinary form or a form with a file
        if(!ServletFileUpload.isMultipartContent(request)){
            return;//Terminate the operation of the method, indicating that this is an ordinary form, which is returned directly
        }
        //Create the save path of the uploaded file. It is recommended that it be safe under the WEB-INF path. Users cannot directly access the uploaded file
        String uploadPath=this.getServletContext().getRealPath("/WEB-INF/upload");
        File uploadFile=new File(uploadPath);
        if(!uploadFile.exists()){
            uploadFile.mkdir();//Create this directory
        }
        System.out.println("Directory created successfully");
        //Cache, temporary file
        //If the file exceeds the specified size, it will be made into a temporary file, which will be automatically deleted in a few days, or the user will be reminded to save it permanently
        String tmpPath=this.getServletContext().getRealPath("/WEB-INF/upload");
        File file=new File(tmpPath);
        if(!file.exists()){
            file.mkdir();//Create this directory
        }
        //Generally, the uploaded files need to be obtained through the stream. We can use request.getInputStream() to obtain the original file upload stream, which is very troublesome
        //However, we all recommend using Apache's file upload component, common fileUpload, which depends on the common IO component:
        /*
            ServletFileUpload It is responsible for processing the uploaded file data and encapsulating each input item in the form into a FileTtem object
            The DiskFileItemFactory object is required when parsing requests using the ServletFileUpload object
            Therefore, we need to construct the DiskFileItemFactory object before parsing
            Set the ServletFileUpload object through the construction method of the ServletFileUpload object or the setFileItemFactory() method
            fileItemFactory property of the object
         */

        DiskFileItemFactory factory=getDiskFileItemFactory(file);
        //        // 🌟 Monitor the progress of file upload
        ServletFileUpload upload=getServletFileUpload(factory);
        //three 🌟 Processing uploaded files
        String msg=uploadParseRequest(upload,request,uploadPath);
   

        //servlet request forwarding message
        request.setAttribute("msg",msg);
        request.getRequestDispatcher("info.jsp").forward(request,response);


    }
    DiskFileItemFactory getDiskFileItemFactory(File file){
        DiskFileItemFactory factory=new DiskFileItemFactory();
        //Set a buffer through this factory. When the uploaded file is larger than this buffer, put it into the temporary file:
        factory.setSizeThreshold(1024*1024);
        factory.setRepository(file);
        return factory;
    }
    ServletFileUpload getServletFileUpload(DiskFileItemFactory factory){
        ServletFileUpload upload=new ServletFileUpload(factory);
        //🌟 Monitor the progress of file upload
        upload.setProgressListener(new ProgressListener() {
            @Override
            //pBytesRead: read file size
            //pContentLength: file size
            public void update(long pBytesRead, long pContentLength, int pItems) {
                System.out.println("Total size:"+pContentLength+"Uploaded:"+pBytesRead);
            }
        });
        //Dealing with garbled code
        upload.setHeaderEncoding("UTF-8");
        //Sets the maximum value for a single file
        upload.setFileSizeMax(1024*1024*10);
        //Set the total size of files that can be uploaded
        //1024=1kb*1024=1M*10=10M
        upload.setSizeMax(1024*1024*10);
        return  upload;
    }
    String uploadParseRequest(ServletFileUpload upload, HttpServletRequest request,String uploadPath){
        String msg="Upload failed";
        try {
            List<FileItem> fileItems=upload.parseRequest(request);
            //fileItem each form object
            for (FileItem fileItem : fileItems) {
                //Determine whether the uploaded file is an ordinary form or a form with a file
                if(fileItem.isFormField()){
                    //getFiledName refers to the name of the front-end form control;
                    String name=fileItem.getFieldName();
                    String value=fileItem.getString("UTF-8");
                    System.out.println(name+":"+value);
                }else{
                    //If it is a file form
                    //1. Processing documents=================
                    String uploadFileName=fileItem.getName();
                    System.out.println("Uploaded file name:"+uploadFileName);
                    //The file name may be illegal
                    if(uploadFileName.trim().equals("")||uploadFileName==null){
                        continue;
                    }
                    //Get the uploaded file name / images/gurl/paojie.png
                    String fileName=uploadFileName.substring(uploadFileName.lastIndexOf("/")+1);
                    //Get the suffix of the file
                    String fileExtName=uploadFileName.substring(uploadFileName.lastIndexOf(".")+1);
                    /*
                     * If the file suffix fileExtName is not what we want
                     * return and tell the user that the file type is wrong
                     * */
                    //You can use UUID (universal code for unique identification) to ensure that the file name is unique
                    //UUID.randomUUID() randomly generates a unique universal code
                    //Everything in network transmission needs to be serialized,
                    //POJO, entity classes can only be used locally. If you want to run on multiple computers, you need to serialize the objects when transmitting = = =
                    //implements Serializable does not have a method interface - "" tag interface. When the JVM virtual machine is running, the JVM's local method stack -- native - > C++
                    //JNI = Java Native Interface - > java localized interface
                    //Java stack
                    //UUID generates random sequence number through bit operation to ensure non repeatability
                    String uuidPath = UUID.randomUUID().toString();
                    //2. Storage address=================
                    //Where? uploadPath
                    //The real path of the file realPath
                    String realPath=uploadPath+"/"+uuidPath;
                    //Create a folder for each file
                    File realPathFile=new File(realPath);
                    if(!realPathFile.exists()){
                        realPathFile.mkdir();
                    }
                    //3. File transfer=================
                    //Get the stream of file upload
                    InputStream inputStream=fileItem.getInputStream();
                    //Create a file output stream
                    //realPath = real folder
                    //One file is missing, plus the name of the output file + "/" + uuidFileName
                    FileOutputStream fos=new FileOutputStream(realPath+"/"+fileName);
                    //Create a buffer
                    byte[] buffer=new byte[1024*1024];
                    //Judge whether the reading is completed
                    int len=0;
                    //If it is greater than 0, data still exists
                    while((len=inputStream.read(buffer))>0){
                        fos.write(buffer,0,len);
                    }
                    msg="Upload file succeeded";
                    //Close flow
                    fos.close();
                    inputStream.close();
                    fileItem.delete();//Upload the file successfully. Clear the temporary file

                }

            }
        } catch (FileUploadException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return  msg;
    }
    protected void doGet(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, IOException {

    }
}

Operation results

If it is helpful to you, please give a free praise point ~ thank you 🙏

Tags: Java Back-end

Posted on Wed, 01 Dec 2021 08:45:11 -0500 by Hatch