“This article has participated in the good article call order activity, click to see: back end, big front end double track submission, 20,000 yuan prize pool for you to challenge!”

I. File upload

File submissions from the user’s local disk are saved to disks on the server.

1.1 existing problems.

To upload a file, the general steps are:

  1. To have a form tag, method= POST request. Because the size is limited in the GET request.
  2. The encType attribute value of the form tag must be the multipart/form-data value.
  3. Add the uploaded file in the form tag using input type=file.
  4. Write server code (Servlet program) to receive and process the uploaded data.

EncType = Multipart /form-data represents submitted data that is pieced together in multiple segments (one for each form item) and sent to the server as a binary stream.

If enctype=”multipart/form-data”, getParameter() cannot retrieve the data.

1.2. Upload Servlet3.0 files

If uploading files is such a headache, someone should help us out. Servlet 3.0 provides file upload operations and is very simple to use.

We just need to post an annotation @multipartConfig to the Servlet and use getPart() to get the file with the name specified in the request to the Part object. Then we can use its API to manipulate the file.

1.3, API

HttpServletRequest provides two methods to parse the uploaded file from the request.

The return value methods role
Part getPart(String name) Used to get the file name specified in the request
Collection getParts() Get all files in the request

Common methods in Part:

The return value methods role
void write(String fileName) Save the received files directly to disk
void getContentType() Gets the MIME type of the file
String getHeader(String name) Gets the request header
long getSize() Gets the size of the file

1.4, code,

package com.servlet;

import java.io.IOException;
import java.net.http.HttpClient;
import javax.servlet.ServletException;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;

/ * * *@author Xiao_Lin
 * @date2021/1/20 9:25 * /
@WebServlet("/fileUpload")
@MultipartConfig
public class FileUploadServlet extends HttpServlet {

  @Override
  protected void service(HttpServletRequest req, HttpServletResponse resp)
      throws ServletException, IOException {
    // For normal parameters, use the original receiving mode
    String username = req.getParameter("username");
    // Obtain the file data
    Part part = req.getPart("headImg");
    // Save to disk, parameter name = drive letter + file name + suffix (own name)
    part.write("d:/headimg.jpg");
Copy the code
<%@page contentType="text/html; UTF-8" pageEncoding="UTF-8" isELIgnored="false" %>
<html>
<body>
<h2>Hello World!</h2>
<form action="/fileUpload" method="post" enctype="multipart/form-data">User name:<input type="text" name="username">Upload file:<input type="file" name="headImg">
    <input type="submit" value="Registered">
</form>
</body>
</html>

Copy the code

2. File upload and expansion

2.1. Obtain the upload file name

We can use the API that uses the Part object.

The return value methods role
String getHeader(“content-disposition”) Before Tocmat 8.0, use the request header to obtain the file name, which needs to intercept the string
String getSubmittedFileName() Tomcat8.0 provided after the direct way to obtain the file name
package com.servlet;

import java.io.IOException;
import java.net.http.HttpClient;
import javax.servlet.ServletException;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;

/ * * *@author Xiao_Lin
 * @date2021/1/20 9:25 * /
@WebServlet("/fileUpload")
@MultipartConfig
public class FileUploadServlet extends HttpServlet {

  @Override
  protected void service(HttpServletRequest req, HttpServletResponse resp)
      throws ServletException, IOException {
    // For normal parameters, use the original receiving mode
    String username = req.getParameter("username");
    // Obtain the file data
    Part part = req.getPart("headImg");
    // Save to disk, parameter name is drive letter + file name + suffix (automatically obtain file name)
    part.write("d:/"+part.getSubmittedFileName()); }}Copy the code

Use UUID to generate file name

If the file name is the same, it will overwrite the previously uploaded file on the server. The solution is to create a unique file

The name of a, make sure not to overwrite, here we use UUID.

package com.servlet;

import java.io.IOException;
import java.net.http.HttpClient;
import java.util.UUID;
import javax.servlet.ServletException;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;

/ * * *@author Xiao_Lin
 * @date2021/1/20 9:25 * /
@WebServlet("/fileUpload")
@MultipartConfig
public class FileUploadServlet extends HttpServlet {

  @Override
  protected void service(HttpServletRequest req, HttpServletResponse resp)
      throws ServletException, IOException {
    // Obtain the file data
      Part part = req.getPart("headImg");
    // Get the file name to upload
    String realName = part.getSubmittedFileName();
    // Get the extension of the file
    String ext = realName.substring(realName.lastIndexOf("."));
    // Generate a unique UUID that will not be repeated
    String fileNewName = UUID.randomUUID().toString()+ext;
    part.write("d://"+fileNewName); }}Copy the code

Note: environment, there is no part in tomcat7 getSubmittedFileName (), this method cannot directly access to the file name, if you are using tomcat7 plugin or Tomcat8 the following version, need to change. Otherwise, an error will be reported.

 String cd = part.getHeader("Content-Disposition");
// Intercepting different types of files requires discretion
 String filename = cd.substring(cd.lastIndexOf("=") +2, cd.length()-1);
Copy the code

2.3. File saving location problem

The file is located somewhere on disk, not under the project, and cannot be accessed using HTTP protocol, so you need to save the file uploaded by the user to the project

Can be accessed through HTTP protocol, and the saved location path can not write the absolute path, so how do we access?

The absolute path of the ServletContext object can be obtained from its getRealPath(” relative path to the folder in the project where the uploaded file is stored “).

Let’s create a new file called upload in the webapps directory to store the file.

package com.servlet;

import java.io.IOException;
import java.net.http.HttpClient;
import java.util.UUID;
import javax.servlet.ServletException;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;

/ * * *@author Xiao_Lin
 * @date2021/1/20 9:25 * /
@WebServlet("/fileUpload")
@MultipartConfig
public class FileUploadServlet extends HttpServlet {

  @Override
  protected void service(HttpServletRequest req, HttpServletResponse resp)
      throws ServletException, IOException {
    // Obtain the file data
      Part part = req.getPart("headImg");
    String cd = part.getHeader("Content-Disposition");
    // Get the file name to upload
    String realName = cd.substring(cd.lastIndexOf("=") +2, cd.length()-1);
    // Get the extension of the file
    String ext = realName.substring(realName.lastIndexOf("."));
    // Generate a unique UUID that will not be repeated
    String fileNewName = UUID.randomUUID().toString()+ext;
    // Select 'upload' from 'upload' and 'file' from 'upload' to 'file'.
    String realPath = req.getServletContext().getRealPath("/upload") +"/"+ fileNewName; part.write(realPath); }}Copy the code

2.4 Constraints on file types

Limit malicious file uploads, such as asking a user to upload an avatar when the user uploads a non-image file, such as a JSP file.

package com.servlet;

import java.io.IOException;
import java.net.http.HttpClient;
import java.util.UUID;
import javax.servlet.ServletException;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;

/ * * *@author Xiao_Lin
 * @date2021/1/20 9:25 * /
@WebServlet("/fileUpload")
@MultipartConfig
public class FileUploadServlet extends HttpServlet {

  @Override
  protected void service(HttpServletRequest req, HttpServletResponse resp)
      throws ServletException, IOException {
    // Obtain the file data
    Part part = req.getPart("headImg");
    System.out.println(part.getContentType());
    // If the file to be uploaded is not an image (file whose extension does not start with image is not an image)
    if(! part.getContentType().startsWith("image/")) {
      req.setAttribute("msg"."Please upload pictures.");
      req.getRequestDispatcher("/index.jsp").forward(req, resp);
      return; }}}Copy the code

2.5. Constraints on file size

Limiting the file upload size increases the server hard disk usage and prevents malicious file uploads from constricting server disk resources. We can limit this by setting @mutipartConfig’s properties, which have two properties:

  1. maxFileSize: Specifies the size limit of a single uploaded file. The unit is bytes.
  2. ·maxRequestSize· : Displays the size of the data in the request, in bytes.
@MultipartConfig(maxFileSize = 80000, maxRequestSize = 140000)
Copy the code

Third, file download

3.1, code,

package com.servlet;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/ * * *@author Xiao_Lin
 * @date2021/1/21 10:58 * /
@WebServlet(urlPatterns = "/download")
public class DownloadServlet extends HttpServlet {

  @Override
  protected void service(HttpServletRequest req, HttpServletResponse resp)
      throws ServletException, IOException {
    // Obtain the name of the file that the user wants to download
    String fileName = req.getParameter("fileName");
    // Obtain the root path of the file
    String realPath = req.getServletContext().getRealPath("/WEB-INF/upload/");
    // Use the copy method of the utility class Files to get an output stream of Files and respond to the browserFiles.copy(Paths.get(realPath,fileName),resp.getOutputStream()); }}Copy the code

3.2 The name of the downloaded file is incorrect

By default, the Tomcat server does not tell the browser the name of the file, so you need to manually set the response header to tell the browser the file name

Said.

// Give the browser a recommended name
resp.setHeader("Content-Disposition"."attachment; Filename = filename");
Copy the code

If there is Chinese in the file, there is also the need to deal with Chinese garbled characters, which is divided into two schools:

  • URLEncoder. Encode (fileName, “utF-8 “)
  • Non-ie uses ISO-8859-1 encoding: new String (filena.getBytes (“UTF-8”), “ISO-8859-1”)
package com.servlet;

import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/ * * *@author Xiao_Lin
 * @date2021/1/21 10:58 * /
@WebServlet(urlPatterns = "/download")
public class DownloadServlet extends HttpServlet {

  @Override
  protected void service(HttpServletRequest req, HttpServletResponse resp)
      throws ServletException, IOException {
    // Obtain the name of the file that the user wants to download
    String fileName = req.getParameter("fileName");
    // Get the browser type
    String header = req.getHeader("User-Agent");
    // If MSIE is included, it means Microsoft's browser (not IE), otherwise it is not IE
    String name = header.contains("MSIE")? URLEncoder.encode(fileName, StandardCharsets.UTF_8) :new String(fileName.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1);
    // Set the download name of the file
    resp.setHeader("Content-Disposition"."attachment; filename=" + name);
    // Obtain the root path of the file
    String realPath = req.getServletContext().getRealPath("/WEB-INF/upload/");
    // Use the copy method of the utility class Files to get an output stream of Files and respond to the browserFiles.copy(Paths.get(realPath,fileName),resp.getOutputStream()); }}Copy the code