内容简介:这时候系统将会出现这是什么原因呢?可以进入而后我们再进入
pom包的配置
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>
启动项类修改
/** * 防止文件大于10M时Tomcat连接重置 * * @return */ @Bean public TomcatServletWebServerFactory tomcatEmbedded() { TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory(); tomcat.addConnectorCustomizers((TomcatConnectorCustomizer) connector -> { if ((connector.getProtocolHandler() instanceof AbstractHttp11Protocol<?>)) { ((AbstractHttp11Protocol<?>) connector.getProtocolHandler()).setMaxSwallowSize(-1); } }); return tomcat; }
配置文件修改
# 禁用 thymeleaf 缓存 spring.thymeleaf.cache=false # 是否支持批量上传 (默认值 true) spring.servlet.multipart.enabled=true # 上传文件的临时目录 (一般情况下不用特意修改) spring.servlet.multipart.location= # 上传文件最大为 1M (默认值 1M 根据自身业务自行控制即可) spring.servlet.multipart.max-file-size=10MB # 上传请求最大为 10M(默认值10M 根据自身业务自行控制即可) spring.servlet.multipart.max-request-size=10MB # 文件大小阈值,当大于这个阈值时将写入到磁盘,否则存在内存中,(默认值0 一般情况下不用特意修改) spring.servlet.multipart.file-size-threshold=0 # 判断是否要延迟解析文件(相当于懒加载,一般情况下不用特意修改) spring.servlet.multipart.resolve-lazily=false file.upload.path: /file/upload
单文件上传
@PostMapping("/upload") public Map<String, String> upload(@RequestParam MultipartFile file) throws IOException { //创建本地文件 File localFile = new File(path, file.getOriginalFilename()); //把传上来的文件写到本地文件 file.transferTo(localFile); //返回localFile文件路径 Map<String, String> path = new HashMap<>(); path.put("path", localFile.getAbsolutePath()); return path; }
这时候系统将会出现 FileNotFoundException
,日志类似下面这样:
java.io.FileNotFoundException:C:\Users\cheng\AppData\Local\Temp\tomcat.7543349588424487992.9000\work\Tomcat\localhost\ROOT\file\upload\tmp\file\upload\1558332190813.jpg (系统找不到指定的路径。)
这是什么原因呢?可以进入 transferTo
方法
@Override public void transferTo(File dest) throws IOException, IllegalStateException { this.part.write(dest.getPath()); if (dest.isAbsolute() && !dest.exists()) { // Servlet 3.0 Part.write is not guaranteed to support absolute file paths: // may translate the given path to a relative location within a temp dir // (e.g. on Jetty whereas Tomcat and Undertow detect absolute paths). // At least we offloaded the file from memory storage; it'll get deleted // from the temp dir eventually in any case. And for our user's purposes, // we can manually copy it to the requested location as a fallback. FileCopyUtils.copy(this.part.getInputStream(), Files.newOutputStream(dest.toPath())); } }
而后我们再进入 write
方法
@Override public void write(String fileName) throws IOException { File file = new File(fileName); if (!file.isAbsolute()) { file = new File(location, fileName); } try { fileItem.write(file); } catch (Exception e) { throw new IOException(e); } }
这时候我们看到如果 file.isAbsolute()
成立,也就是我们没有使用绝对路径,那么 file = new File(location,fileName);
会在原来的基础上加上location路径.这就是原因所在,可以通过修改绝对路径解决
- 直接将file.upload.path修改为绝对路径即可
-
在代码中控制
@PostMapping("/upload") public Map<String, String> upload(@RequestParam MultipartFile file) throws IOException { //创建本地文件 String classpath = ResourceUtils.getURL("classpath:").getPath(); File localFile = new File(classpath + path, file.getOriginalFilename()); //把传上来的文件写到本地文件 file.transferTo(localFile); //返回localFile文件路径 Map<String, String> path = new HashMap<>(); path.put("path", localFile.getAbsolutePath()); return path; }
通过
ResourceUtils.getURL("classpath:").getPath()
获得项目路径,然后加上设置的相对路径。网络上还有一种修改
location
值的方式,可以看 这篇博客 但是我个人使用是一直不可以。 -
或者可以不使用transferTo,代码如下
@PostMapping("/singleFileUpload") public String singleFileUpload(@RequestParam("file") MultipartFile file) throws IOException { byte[] bytes = file.getBytes(); Path filePath = Paths.get(path + file.getOriginalFilename()); Files.write(filePath, bytes); return file.getOriginalFilename(); }
Paths.get
所使用的也是绝对路径,如果您在Windows机器上使用了这种路径(从/开始的路径),那么路径将被解释为相对于当前驱动器,例如/file/upload/1.txt
而您的项目位于D盘。那么这条路径就会对应这条完整的路径:
D:\file\upload\1.txt
为了简便,以下代码均是使用绝对路径。
文件上传控制器编写
多文件上传
@PostMapping("/uploads") public Map<String, String> uploads(@RequestParam MultipartFile[] files) throws IOException { StringBuilder sb = new StringBuilder(); Map<String, String> paths = new HashMap<>(); for (MultipartFile file : files) { //创建本地文件 File localFile = new File(path, file.getOriginalFilename()); //把传上来的文件写到本地文件 file.transferTo(localFile); sb.append(localFile.getAbsolutePath()).append(","); paths.put(file.getOriginalFilename(), localFile.getAbsolutePath()); } //返回localFile文件路径 return paths; }
多文件上传+表单提交
@PostMapping("/uploadsWithForm") public Map<String, String> uploadsWithForm(@RequestParam String tmpString, @RequestParam MultipartFile[] files) throws IOException { StringBuilder sb = new StringBuilder(); Map<String, String> paths = new HashMap<>(); paths.put("tmpString", tmpString); for (MultipartFile file : files) { //创建本地文件 File localFile = new File(path, file.getOriginalFilename()); //把传上来的文件写到本地文件 file.transferTo(localFile); sb.append(localFile.getAbsolutePath()).append(","); paths.put(file.getOriginalFilename(), localFile.getAbsolutePath()); } //返回localFile文件路径 return paths; }
多文件上传+Json数据提交
/** * 测试多文件上传+json接口 * * @param files * @return */ @ApiOperation("测试多文件上传接口") @ApiImplicitParams({ @ApiImplicitParam(name = "jsonMap", value = "json数据", dataType = "Map"), @ApiImplicitParam(name = "files", value = "文件流对象,接收数组格式", required = true, dataType = "__File"), }) @PostMapping(value = "/uploadsWithJson") public Map<String, String> uploadsWithJson(@RequestPart("files") MultipartFile[] files, @RequestPart("jsonMap") Map<String, Object> jsonMap) throws IOException { StringBuilder sb = new StringBuilder(); Map<String, String> paths = new HashMap<>(); System.out.println(jsonMap); for (MultipartFile file : files) { //创建本地文件 File localFile = new File(path, file.getOriginalFilename()); //把传上来的文件写到本地文件 file.transferTo(localFile); sb.append(localFile.getAbsolutePath()).append(","); paths.put(file.getOriginalFilename(), localFile.getAbsolutePath()); } paths.put("jsonMap", JsonUtils.obj2json(jsonMap)); //返回localFile文件路径 return paths; }
呵呵,不好用对不对。项目抛出了个异常, HttpMediaTypeNotSupportedException
。
WARN o.s.w.s.m.support.DefaultHandlerExceptionResolver - Resolved [org.springframework.web.HttpMediaTypeNotSupportedException: Content type 'application/octet-stream' not supported]
所以我们需要添加个转换器类
@Component public class MultipartJackson2HttpMessageConverter extends AbstractJackson2HttpMessageConverter { /** * Converter for support http request with header Content-Type: multipart/form-data */ public MultipartJackson2HttpMessageConverter(ObjectMapper objectMapper) { super(objectMapper, MediaType.APPLICATION_OCTET_STREAM); } @Override public boolean canWrite(Class<?> clazz, MediaType mediaType) { return false; } @Override public boolean canWrite(Type type, Class<?> clazz, MediaType mediaType) { return false; } @Override protected boolean canWrite(MediaType mediaType) { return false; } }
这样就能够识别了
总结
感觉把springboot文件上传所能遇到的坑全踩了个变,心累。
如果需要项目代码,可以去我的 github 中下载;
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
A Philosophy of Software Design
John Ousterhout / Yaknyam Press / 2018-4-6 / GBP 14.21
This book addresses the topic of software design: how to decompose complex software systems into modules (such as classes and methods) that can be implemented relatively independently. The book first ......一起来看看 《A Philosophy of Software Design》 这本书的介绍吧!
MD5 加密
MD5 加密工具
RGB CMYK 转换工具
RGB CMYK 互转工具