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
- 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
- To prevent file overwriting, a unique file name (- timestamp UUID MD5 bit operation) should be generated for the uploaded file
- To limit the maximum number of uploaded files
- 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 { } }