1. Overview

The Apache Commons File Upload Library helps us upload large files over the HTTP protocol using the multipart/form-data content type.

In this quick tutorial, we’re going to take a look at how to integrate it with Spring.

2. Maven Dependencies

To use the library, we’ll need the commons-fileupload2-jakarta artifact:

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-fileupload2-jakarta</artifactId>
    <version>2.0.0-M1</version>
</dependency>

The latest version can be found on Maven Central.

3. Transfering All at Once

For demonstration purposes, we’re going to create a Controller processing requests with a file payload:

@PostMapping("/upload")
public String handleUpload(HttpServletRequest request) throws Exception {
    boolean isMultipart = JakartaServletFileUpload.isMultipartContent(request);

    DiskFileItemFactory factory = DiskFileItemFactory.builder().get();
    JakartaServletFileUpload upload = new JakartaServletFileUpload(factory);

    List items = upload.parseRequest(request);

    Iterator iter = items.iterator();
    while (iter.hasNext()) {
        FileItem item = iter.next();

        if (!item.isFormField()) {
            try (
              InputStream uploadedStream = item.getInputStream();
              OutputStream out = new FileOutputStream("file.mov");) {

                IOUtils.copy(uploadedStream, out);
            }
        }
    }    
    return "success!";
}

In the beginning, we need to check if the request contains a multipart content using the isMultipartContent method found in the ServletFileUpload class from the library.

By default, Spring features a MultipartResolver that we’ll need to disable to use this library. Otherwise, it’ll read the content of the request before it reaches our Controller.

We can achieve this by including this configuration in our application.properties file:

spring.http.multipart.enabled=false

The library provides a DiskFileItemFactory class that takes the responsibility of the configuration for the file saving and cleaning. We can create one using the DiskFileItemFactory.builder() method. We have to use the builder as the direct constructor is private.

Now we can continue to the actual file handling.

First, we create our JakartaServletFileUpload by including our previously created factory; then we proceed to parse the request and generate a list of FileItem which are the main abstraction of the library for the form fields.

Now if we know it isn’t a normal form field, then we proceed to extract the InputStream and to call the useful copy method from IOUtils (for more options you can have a look at this tutorial).

Now we have our file stored in the necessary folder. This is usually a more convenient way to handle this situation as it allows easy access to the files, but also time/memory efficiency isn’t optimal.

In the next section, we’re going to take a look at the streaming API.

4. Streaming API

The streaming API is easy to use, making it a great way to process large files simply by not copying to a temporary location:

JakartaServletFileUpload upload = new JakartaServletFileUpload();
FileItemInputIterator iterStream = upload.getItemIterator(request);
while (iterStream.hasNext()) {
    FileItemInput item = iterStream.next();
    String name = item.getFieldName();
    InputStream stream = item.getInputStream();
    if (!item.isFormField()) {
        // Process the InputStream
    } else {
        String formFieldValue = IOUtils.toString(stream, StandardCharsets.UTF_8);
    }
}

We can see in the previous code snippet that we no longer include a DiskFileItemFactory. This is because, when using the streaming API, we don’t need it.

Next, to process fields, the library provides a FileItemInputIterator, which doesn’t read anything until we extract them from the request with the next method.

Finally, we can see how to obtain the values of the other form fields.

5. Conclusion

In this article, we’ve reviewed how we can use the Apache Commons File Upload Library with Spring to upload and process large files.

As always the full source code can be found over at GitHub.


« 上一篇: 跨微服务事务实现
» 下一篇: Java 操作Google Sheet