赞
踩
如下所示的代码,是一个在springboot项目中使用MultipartFile进行文件上传的示例:
- package com.springboot.web;
-
- import org.springframework.http.ResponseEntity;
- 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.util.HashMap;
- import java.util.Map;
-
- @RestController
- @RequestMapping("/test")
- public class UploadController {
-
- private String path = "d:/temp";
-
- @PostMapping("/upload")
- public ResponseEntity upload(MultipartFile file) {
- Map<String,Object> res = new HashMap<>();
- try {
- File outFile = new File(path.concat(File.separator).concat(file.getOriginalFilename()));
- file.transferTo(outFile);
- res.put("url",outFile.getAbsolutePath());
- res.put("code",200);
- } catch (Exception e) {
- e.printStackTrace();
- res.put("msg","upload fail");
- res.put("code",500);
- }
- return ResponseEntity.ok(res);
- }
- }
我们在前端页面上,进行配置上传的时候,可以使用这样的form:
- <form action="/test/upload" method="post" enctype="multipart/form-data">
- <input type="file" name="file"/>
- <input type="submit" value="upload"/>
- </form>
这里需要注意的是,前端的元素<input type="file" name="file"/>这里的name属性,它要和后端接口里面MultipartFile file参数名字对应起来。否则,接口会报空指针异常。
现在web一般流行的是异步上传,所以使用三方javascript框架的时候,也需要注意,这里代表file的属性名一定要指定为file,与接口中参数file名字对应起来。
到这里,使用MultipartFile上传文件基本就完成了,但是,我们这种接口有一个问题,如果我们使用三方服务来调用这个接口,那么这个参数MultipartFile还不好传递,因为这个类型是一个接口类型:
- public interface MultipartFile extends InputStreamSource {
- String getName();
-
- @Nullable
- String getOriginalFilename();
-
- @Nullable
- String getContentType();
-
- boolean isEmpty();
-
- long getSize();
-
- byte[] getBytes() throws IOException;
-
- InputStream getInputStream() throws IOException;
-
- default Resource getResource() {
- return new MultipartFileResource(this);
- }
-
- void transferTo(File dest) throws IOException, IllegalStateException;
-
- default void transferTo(Path dest) throws IOException, IllegalStateException {
- FileCopyUtils.copy(this.getInputStream(), Files.newOutputStream(dest));
- }
- }
如果java后端来写这个接口调用,我们本地的文件File有的是,问题是怎么把这个File转为MultipartFile,有一种办法就是借助spring-test依赖下的MockMultipartFile类型,代码如下所示:
- package com.springboot.web;
-
- import org.junit.Before;
- import org.junit.Test;
- import org.junit.runner.RunWith;
-
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.boot.test.context.SpringBootTest;
- import org.springframework.mock.web.MockMultipartFile;
- import org.springframework.test.context.junit4.SpringRunner;
- import org.springframework.test.web.servlet.MockMvc;
- import org.springframework.test.web.servlet.MvcResult;
- import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
- import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
- import org.springframework.test.web.servlet.setup.MockMvcBuilders;
- import org.springframework.web.context.WebApplicationContext;
-
- import java.io.File;
- import java.io.FileInputStream;
-
- @SpringBootTest
- @RunWith(SpringRunner.class)
- public class UploadControllerTest {
-
- private MockMvc mockMvc;
-
- @Autowired
- private WebApplicationContext webApplicationContext;
-
- @Before
- public void setup() {
- mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
- }
-
- @Test
- public void upload() {
- FileInputStream inputStream = null;
- File file = new File("c:\\users\\buejee\\pictures\\avatar.png");
- try {
- inputStream = new FileInputStream(file);
- MockMultipartFile multipartFile = new MockMultipartFile(
- "file",
- file.getName(),
- "APPLICATION_OCTET_STREAM",
- inputStream);
- MvcResult result = mockMvc.perform(
- MockMvcRequestBuilders
- .fileUpload("/test/upload")
- .file(multipartFile))
- .andExpect(MockMvcResultMatchers.status().isOk())
- .andReturn();
- String response = result.getResponse().getContentAsString();
- System.out.println(response);
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }
这里的核心代码就是这几行:
- FileInputStream inputStream = null;
- File file = new File("c:\\users\\buejee\\pictures\\avatar.png");
- inputStream = new FileInputStream(file);
- MockMultipartFile multipartFile = new MockMultipartFile(
- "file",
- file.getName(),
- "APPLICATION_OCTET_STREAM",
- inputStream);
在构造MockMultipartFile的时候,我们传入的第一个参数就是file,这个还是上面说的,需要和接口中MultipartFile file参数的名称对应起来。
如果不想使用spring-test依赖下的MockMultipartFile,那么就只能自定义一个MultipartFile的实现,其实实现过程完全可以参考MockMultipartFile:
- public class MockMultipartFile implements MultipartFile {
- private final String name;
- private final String originalFilename;
- @Nullable
- private final String contentType;
- private final byte[] content;
-
- public MockMultipartFile(String name, @Nullable byte[] content) {
- this(name, "", (String)null, (byte[])content);
- }
-
- public MockMultipartFile(String name, InputStream contentStream) throws IOException {
- this(name, "", (String)null, (byte[])FileCopyUtils.copyToByteArray(contentStream));
- }
-
- public MockMultipartFile(String name, @Nullable String originalFilename, @Nullable String contentType, @Nullable byte[] content) {
- Assert.hasLength(name, "Name must not be empty");
- this.name = name;
- this.originalFilename = originalFilename != null ? originalFilename : "";
- this.contentType = contentType;
- this.content = content != null ? content : new byte[0];
- }
-
- public MockMultipartFile(String name, @Nullable String originalFilename, @Nullable String contentType, InputStream contentStream) throws IOException {
- this(name, originalFilename, contentType, FileCopyUtils.copyToByteArray(contentStream));
- }
-
- public String getName() {
- return this.name;
- }
-
- @NonNull
- public String getOriginalFilename() {
- return this.originalFilename;
- }
-
- @Nullable
- public String getContentType() {
- return this.contentType;
- }
-
- public boolean isEmpty() {
- return this.content.length == 0;
- }
-
- public long getSize() {
- return (long)this.content.length;
- }
-
- public byte[] getBytes() throws IOException {
- return this.content;
- }
-
- public InputStream getInputStream() throws IOException {
- return new ByteArrayInputStream(this.content);
- }
-
- public void transferTo(File dest) throws IOException, IllegalStateException {
- FileCopyUtils.copy(this.content, dest);
- }
- }
构造出了MultipartFile实例,那么调用上传接口就方便了,在上面给出的上传接口UploadController.upload(MultipartFile file)中,其实隐含了一个操作,就是MultipartFile转File,直接借助MultipartFile.transferTo()就可以写为File类型了,最后我们返回File就可以。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。