“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:
- To have a form tag, method= POST request. Because the size is limited in the GET request.
- The encType attribute value of the form tag must be the multipart/form-data value.
- Add the uploaded file in the form tag using input type=file.
- 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:
maxFileSize
: Specifies the size limit of a single uploaded file. The unit is bytes.- ·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