Spring REST Multipart 之 多次上传示例

了解如何使用Spring REST API接受多个MultipartFile请求数组来上传多个多部分二进制文件(例如jpeg图像)。

1。 Maven依赖

除了spring webmvc之外,我们还需要commons-fileuploadcommons-io类路径。

pom.xml
dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>5.1.6.RELEASE</version>
</dependency>
<dependency>
    <groupId>commons-fileupload</groupId>
    <artifactId>commons-fileupload</artifactId>
    <version>1.4</version>
</dependency>
<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.6</version>
</dependency>

2.配置CommonsMultipartResolver

它是的基于Servlet的MultipartResolver实现commons-fileupload。它提供“ maxUploadSize ”,“ maxInMemorySize ”和“ defaultEncoding ”设置作为bean属性。

此类的目的是将临时文件保存到Servlet容器的临时目录中。

rest-servlet.xml
<beans>
    ...
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <property name="maxUploadSize" value="1000000"/>
    </bean>
    ...
</beans>

等效的Java注解配置为:

@Bean(name = "multipartResolver")
public CommonsMultipartResolver multipartResolver()
{
    CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver();
    multipartResolver.setMaxUploadSize(20848820);
    return multipartResolver;
}

3.创建多个上载Rest API

创建给定的REST API,它将负责处理发布到服务器的多个上载。在给出的示例中,我在path处创建了API /employee-management/employees/1/photo/multiple

我假设'1'在数据库中存在具有ID的员工。随时更改资源路径和实现。

EmployeeImageController.java
package com.how2codex.demo.controller;
import static org.springframework.web.servlet
        .support.ServletUriComponentsBuilder.fromCurrentRequest;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URI;
import java.util.concurrent.Callable;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import com.how2codex.demo.exception.RecordNotFoundException;
import com.how2codex.demo.model.Employee;
import com.how2codex.demo.repository.EmployeeRepository;
@RestController
@RequestMapping(value = "/employee-management/employees/{id}/photo")
@PropertySource("classpath:application.properties")
public class EmployeeImageController {
    @Autowired
    private EmployeeRepository repository;
    private File uploadDirRoot;
    @Autowired
    EmployeeImageController(@Value("${image.upload.dir}") String uploadDir,
                                        EmployeeRepository repository) {
        this.uploadDirRoot = new File(uploadDir);
        this.repository = repository;
    }
    @PostMapping(value = "/multiple", consumes = { "multipart/form-data" })
    Callable<ResponseEntity<?>> writeMultiple(@PathVariable Long id,
                    @RequestParam("files") MultipartFile[] files) throws Exception
    {
        return () -> this.repository.findById(id).map(employee ->
        {
            
            Arrays.asList(files).stream().forEach(file ->
            {
                File fileForEmployee;
                try {
                    fileForEmployee = uploadPath(employee, file);
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
                try (InputStream in = file.getInputStream(); OutputStream out = new FileOutputStream(fileForEmployee)) {
                    FileCopyUtils.copy(in, out);
                } catch (IOException ex) {
                    throw new RuntimeException(ex);
                }
            });
            return ResponseEntity.ok().build();
        }).orElseThrow(() -> new RecordNotFoundException("Employee id is not present in database"));
    }
    private File uploadPath(Employee e, MultipartFile file) throws IOException
    {
        File uploadPath = Paths.get(this.uploadDirRoot.getPath(), e.getId().toString()).toFile();
        if(uploadPath.exists() == false) {
            uploadPath.mkdirs();
        }
        return new File(uploadPath.getAbsolutePath(), file.getOriginalFilename());
    }
}

如果文件系统中尚不存在上述REST控制器,则会创建一个上载文件夹(名称为员工ID)。仍然需要定义以下属性。

application.properties
image.upload.dir=c:/temp/images

同样,控制器返回Callable,这意味着该方法会在IO操作可能运行时立即返回。上传过程完成后,API将返回响应。为了使异步支持,配置异步支持DispatcherServlet

web.xml
<web-app>
    <display-name>Employee Management REST APIs</display-name>
    
    <servlet>
        <servlet-name>rest</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
        <async-supported>true</async-supported>
    </servlet>
    <servlet-mapping>
        <servlet-name>rest</servlet-name>
        <url-pattern>/api/rest/*</url-pattern>
    </servlet-mapping>
</web-app>

4.多个分段上传请求演示

出于演示目的,我创建了一个JSP页面,其中仅包含file类型的多个字段。我们将从计算机浏览一些图像,并将其上传到服务器。

multipleFileUpload.jsp
<html>
<head>
<title>Spring REST File Upload</title>
</head>
<body>
    <form method="POST" action="/SpringRestExample/api/rest/employee-management/employees/1/photo/multiple"
        enctype="multipart/form-data">
        <table>
            <tr>
                <td>Select first file to upload</td>
                <td><input type="file" name="files" /></td>
            </tr>
            <tr>
                <td>Select second file to upload</td>
                <td><input type="file" name="files" /></td>
            </tr>
            <tr>
                <td>Select third file to upload</td>
                <td><input type="file" name="files" /></td>
            </tr>
            <tr>
                <td><input type="submit" value="Submit" /></td>
            </tr>
        </table>
    </form>
</body>
</html>

现在启动服务器并在URL中打开上传页面http://localhost:8080/SpringRestExample/multipleFileUpload.jsp。浏览图像,然后单击提交按钮。图像文件将被上传到配置的上传目录中的服务器。

要下载文件,请/employee-management/employees/1/photo在浏览器中输入URL ,然后将显示图像。下载API已包含在附件中。

请问您有关创建Spring MVC REST API来处理多个文件(例如图像)上传问题。

saigon has written 1445 articles

Leave a Reply