First, Requirements Introduction:
Spittr applications require file uploads in two places. When new users sign up for apps, we want them to be able to upload an image to associate with their personal information. When a user submits a new spittle, they may upload a photo in addition to the text message.
Ii. introduction of multipart
The result of the request of the general form submission is very simple, that is, the "&" character is divided into multiple name-value pairs. However, when uploading binary data, such as uploading pictures, there is a problem. In contrast , data in multipart format splits a form into multiple parts (part), each of which corresponds to an input field. In the general form input field, it will be placed in the corresponding part of the text type data, but if you upload the file, it can be the corresponding part of the binary, the following shows the multipart request body:
In this multipart request, we can see that the Profilepicture section is significantly different from the rest. In addition to other content, it has its own ContentType header, which indicates that it is a JPEG image. Although not necessarily obvious, the profilepicture part of the request body is binary data, not simple text.
Although multipart requests seem complicated, it is easy to handle them in spring MVC. Before writing the Controller method to handle file uploads, you must configure a multipart parser that tells Dispatcherservlet how to read the multipart request.
Third, configure the multipart parser
Dispatcherservlet does not implement any function to parse multipart request data. It delegates the task to the implementation of the Multipartresolver policy interface in spring, which resolves the contents of the multipart request through this implementation class. Starting with Spring 3.1, Spring has built-in two multipartresolver implementations to choose from:
-
- Commonsmultipartresolver: Use Jakarta Commons FileUpload to parse the multipart request;
- Standardservletmultipartresolver: Dependent on Servlet 3.0 support for multipart requests (starting with Spring 3.1).
Generally speaking, standardservletmultipartresolver may be the preferred solution between the two. It uses the functionality provided by the servlet to support it and does not need to rely on any other project.
1. Resolving multipart requests using servlet 3.0
Standardservletmultipartresolver compatible with Servlet 3.0 has no constructor parameters and no properties to set. Thus, in the context of the spring application, declaring it as a bean is straightforward, as follows:
1 @Bean 2 Public Multipartresolver Multipartresolver () throws IOException {3 return New standardservletmultipartresolver (); 4 }
If we want to limit the size of the user's upload file, how can it be implemented? How do we do this if we want to specify where the file is temporarily written to when it is uploaded? Because there are no attributes and constructor parameters, the functionality of Standardservletmultipartresolver may seem somewhat limited.
In fact, this is not the case, we have the means to configure the Standardservletmultipartresolver restrictions. Instead of configuring Standardservletmultipartresolver in spring, you specify the configuration of multipart in the servlet. At the very least, we have to specify the path to the temporary file that is written during the file upload process. If you do not set this most basic configuration, Standardservlet-multipartresolver will not work properly. Specifically, we have to use the specifics of multipart as part of the Dispatcherservlet configuration in the Web. Xml or servlet initialization class.
Because the configuration we've been using is Dispatcherservlet's Servlet initialization class inherits the Abstract Annotationconfigdispatcherservletinitializer, the Dispatcherservlet instance is not created directly and registered in the servlet context. In this case, there will be no references to the dynamic Servlet registration for our use. However, we can configure the specifics of multipart by overloading the Customizeregistration () method (which will get a dynamic as a parameter):
1 @Override 2 protected void Customizeregistration (Dynamic registration) { 3 // TODO auto-generated Method stub 4 // Super.customizeregistration (registration); 5 registration.setmultipartconfig (new Multipartconfigelement ( " /tmp/spittr/uploads 6 }
The code uses a multipartconfigelement constructor with only one parameter, which specifies an absolute directory in the file system, and the uploaded file is temporarily written to the directory. However, it is also possible to limit the size of the uploaded file through other constructors. In addition to the location of the temporary path, the other constructors can accept the following parameters:
-
- The maximum size, in bytes, of the uploaded file. The default is no limit.
- The maximum capacity, in bytes, for the entire multipart request, and does not care about how many part and the size of each part. The default is no limit.
- During the upload process, if the file size reaches a specified maximum capacity (in bytes), it will be written to the temporary file path. The default value is 0, which means that all uploaded files will be written to disk.
For example, suppose we want to limit the size of a file to no more than 2MB, the entire request is not more than 4MB, and all the files are written to disk. The following code sets these thresholds using Multipartconfigelement:
1 @Override 2 protected void Customizeregistration (Dynamic registration) { 3 // TODO auto-generated Method stub 4 registration.setmultipartconfig (new Multipartconfigelement ( " /tmp/spittr/uploads ", 2097152 , 4194304 , 0 5 }
If we use the more traditional Web. Xml to configure Multipartconfigelement, then you can use the <multipart-config> element in <servlet> as follows:
2. Configuring the Jakarta Commons FileUpload multipart Parser
Generally speaking, Standardservletmultipartresolver will be the best choice, but if we need to deploy the application to a container other than Servlet 3.0, then we need an alternative scenario.
Spring has a built-in commonsmultipartresolver that can be used as an alternative to standardservletmultipartresolver.
The simplest way to declare commonsmultipartresolver as a spring bean is as follows:
1 @Bean 2 Public Multipartresolver Multipartresolver () throws IOException {3 return New commonsmultipartresolver (); 4 }
Unlike Standardservletmultipartresolver, Commonsmultipart-resolver does not enforce the requirement to set a temporary file path. By default, this path is the temporary directory for the servlet container. However, by setting the Uploadtempdir property, we can specify it as a different location:
In fact, we can specify other multipart upload details in the same way, that is, setting the properties of the Commonsmultipartresolver. For example, the following configuration is equivalent to the Standardservletmultipartresolver we configured in the previous article through Multipartconfigelement:
Here, we set the maximum file capacity to 2MB, and the maximum memory size is set to 0 bytes. These two properties correspond directly to the second and fourth constructor parameters of Multipartconfigelement, indicating that files over 2MB cannot be uploaded, and all files are written to disk regardless of the size of the file. However, unlike multipartconfigelement, we cannot set the maximum capacity of the multipart request as a whole.
Iv. Processing of multipart requests
Now that we have configured the processing of the Mutipart request in spring (or in the servlet container), we can then write the controller method to receive the uploaded file. The most common way to achieve this is to add @requestpart annotations on a controller method parameter.
Suppose we allow a user to upload an image when registering for the spittr application, then we need to modify the form to allow the user to select the image to upload, and to modify the Processregistration () method in the Spittercontroller to connect Upload the image.
<form> tags now set the Enctype property to Multipart/formdata, which tells the browser to submit the form as multipart data, rather than submitting it as form data. In multipart, each input field corresponds to a part.
In addition to the input fields already in the registration form, we have added a new <input> domain whose type is file. This allows the user to select the image file to upload. The Accept property is used to restrict file types to JPEG, PNG, and GIF pictures. According to its Name property, the picture data is sent to the profilepicture part in the multipart request.
We need to modify the Processregistration () method so that it can accept uploaded images. One way is to add a byte array parameter and add a @requestpart annotation to it. The following example:
When the registration form is submitted, the Profilepicture property will be given a byte array that contains the data for the part in the request (specified by @RequestPart). If the user submits the form without selecting the file, the array will be empty (not null). After getting the picture data, the Processregistration () method has the remaining task of saving the file to a location.
1. Accept Multipartfile (How to convert a byte array to a file that can be stored.) )
Using the original byte of the uploaded file is simpler but has limited functionality. As a result, spring also provides the Multipartfile interface, which provides a richer object for processing multipart data. The following list of programs shows an overview of the Multipartfile interface.
Notes the advanced techniques of Spring MVC-processing data in multipart form