基于restful api格式的文件上传(只是上传到本地):
package com.nxz.controller; import com.nxz.entity.FileInfo; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; import java.io.File; import java.io.IOException; import java.util.Date; @RestController @RequestMapping("/file") public class FileController { @PostMapping public FileInfo update(MultipartFile file) throws IOException { System.out.println(file.getName()); System.out.println(file.getOriginalFilename()); System.out.println(file.getSize()); String holder = "G:\0001-myproject\mysecurity\mysecurity-demo\src\main\java\com\nxz\controller"; File localFile = new File(holder, new Date().getTime() + ".txt"); file.transferTo(localFile); return new FileInfo(localFile.getAbsolutePath()); } }
测试用例:
//伪造的mvc环境 @Autowired private WebApplicationContext webApplicationContext; private MockMvc mockMvc; @Before public void before() { mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build(); } @Test public void whenUploadSuccess() throws Exception { String file = mockMvc.perform(MockMvcRequestBuilders.fileUpload("/file") .file(new MockMultipartFile("file", "test.txt", "multipart/form-data", "hello".getBytes("UTF-8")))) .andExpect(MockMvcResultMatchers.status().isOk()) .andReturn().getResponse().getContentAsString(); System.out.println(file); }
测试用例执行完之后输出文件绝对路径:
{"path":"G:\mysecurity\mysecurity-demo\src\main\java\com\nxz\controller\1556463660034.txt"}
下载:
@GetMapping("/{id}") public void downLoad(@PathVariable String id, HttpServletRequest request, HttpServletResponse response) throws IOException { String holder = "G:\0001-myproject\mysecurity\mysecurity-demo\src\main\java\com\nxz\controller"; try ( InputStream inputStream = new FileInputStream(new File(holder, id + ".txt")); OutputStream outputStream = response.getOutputStream(); ) { response.setContentType("application/x-download"); response.addHeader("Content-Disposition", "attachment;filename=test.txt");//重新定义下载后名称 //将文件输入流复制到输出刘超过年 commons-io依赖 IOUtils.copy(inputStream, outputStream); outputStream.flush(); } }
访问:http://localhost:8080/user/1
springboot中上传文件:
java中和文件上传的类又两个:CommonsMultipartResolver,另一个就是StandardServletMultipartResolver,其中commonsMultipartResolver需要commons-fileupload支持,二StandardServletMultipartReslover是servlet3.0默认支持的,tomcat7以上版本就开始支持servlet7.0,springboot22.0之后支持的tomcat版本在7之后,因此是支持StandardServletMultipartReslover的
首先 springboot只要配置好pom(有spring-boot-starter-web依赖),就能自动支持文件上传(包括单文件和多文件),那么springboot中文件上传是怎样起作用的
1、pom依赖,下边这些依赖中,和配置文件上传有关的就是spring-boot-autoconfig依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> ---->>> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> <version>2.1.3.RELEASE</version> <scope>compile</scope> </dependency> ---->>>> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-autoconfigure</artifactId> <version>2.1.3.RELEASE</version> <scope>compile</scope> </dependency>
2、那么看下spring-boot-autoconfig jar包中的spring.factories文件中的内容,这个文件中全都是和springboot自动配置相关的类的全文件名,其中和文件上传有关的是
org.springframework.boot.autoconfigure.web.servlet.MultipartAutoConfiguration,
3、进入这个类中(具体个各种autoconfiguration自动加载类是什么时候加载的,需要看springboot的启动来注解和启动类)
@Configuration
@ConditionalOnClass({ Servlet.class, StandardServletMultipartResolver.class,
MultipartConfigElement.class }) //这个注解表示存在servlet、StandardServletMultipartResolver、multipartConfigElement文件时才加载该类
@ConditionalOnProperty(prefix = "spring.servlet.multipart", name = "enabled", matchIfMissing = true)//配置文件的前缀
@ConditionalOnWebApplication(type = Type.SERVLET)//servlet
@EnableConfigurationProperties(MultipartProperties.class)//配置文件类
public class MultipartAutoConfiguration {
private final MultipartProperties multipartProperties;
public MultipartAutoConfiguration(MultipartProperties multipartProperties) {
this.multipartProperties = multipartProperties;
}
@Bean
@ConditionalOnMissingBean({ MultipartConfigElement.class,
CommonsMultipartResolver.class })//当没有commonsMultipartResolver文件时,初始化该bean
public MultipartConfigElement multipartConfigElement() {
return this.multipartProperties.createMultipartConfig();
}
@Bean(name = DispatcherServlet.MULTIPART_RESOLVER_BEAN_NAME)
@ConditionalOnMissingBean(MultipartResolver.class)
public StandardServletMultipartResolver multipartResolver() {
StandardServletMultipartResolver multipartResolver = new StandardServletMultipartResolver();//springboot默认的文件上传的类
multipartResolver.setResolveLazily(this.multipartProperties.isResolveLazily());
return multipartResolver;
}
}