解决使用Spring Boot、Multipartfile上传文件路径错误问题

彻底跟路径错误say拜拜!

题图:from Google

1.问题描述

  • 关键字: SpringMVC 4.2.4 、 Spring Boot 1.3.1 、Servlet 3.0 、文件上传
  • 报错信息: java.io.IOException: java.io.FileNotFoundException: /tmp/tomcat.273391201583741210.8080/work/Tomcat/localhost/ROOT/tmp/source/IMG_20160129_132623.jpg (No such file or directory)
  • 问题源码: transferTo方法报错
// 前端传入mulFileSource
// 创建压缩前源文件
File fileSourcePath = new File("tmp/source/");
File fileSource = new File(fileSourcePath, mulFileSource.getOriginalFilename());
if (!fileSourcePath.exists()) {
    fileSourcePath.mkdirs();
}
// 将接收得图片暂存到临时文件中
mulFileSource.transferTo(fileSource);

 

2.问题分析

  • 首先,看源码中文件定义,相对路径,预期路径应该是项目路径/tmp/source/,但是报错确是一个系统临时文件路径(tomcat的)。
  • 其次,由于是transferTo方法报错,因此应该是该方法写入文件时报错,因此,我们跟入方法源码。
public class StandardMultipartHttpServletRequest extends AbstractMultipartHttpServletRequest {

//中间代码省略

/**
 * Spring MultipartFile adapter, wrapping a Servlet 3.0 Part object.
 */
@SuppressWarnings("serial")
private static class StandardMultipartFile implements MultipartFile, Serializable {

    //中间代码省略
    @Override
    public void transferTo(File dest) throws IOException, IllegalStateException {
        this.part.write(dest.getPath());
        }
    }
}

源码一目了然,使用Servlet3.0的支持的上传文件功能时,如果我们没有使用绝对路径的话,transferTo方法会在相对路径前添加一个location路径,即:file = new File(location, fileName);。当然,这也影响了SpringMVC的Multipartfile的使用。

package org.apache.catalina.core;
/**
 * Adaptor to allow {@link FileItem} objects generated by the package renamed
 * commons-upload to be used by the Servlet 3.0 upload API that expects
 * {@link Part}s.
 */
public class ApplicationPart implements Part {

//中间代码省略

    @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);
        }
    }
}


3.问题解决方案
由于我们创建的File在项目路径/tmp/source/,而transferTo方法预期写入的文件路径为/tmp/tomcat.273391201583741210.8080/work/Tomcat/localhost/ROOT/tmp/source/,我们并没有创建该目录,因此会抛出异常。

  1. 使用绝对路径
  2. 修改location的值
    这个location可以理解为临时文件目录,我们可以通过配置location的值,使其指向我们的项目路径,这样就解决了我们遇到的问题。
    在Spring Boot下配置location,可以在main()方法所在文件中添加如下代码:
/**
 * 文件上传临时路径
 */
 @Bean
 MultipartConfigElement multipartConfigElement() {
    MultipartConfigFactory factory = new MultipartConfigFactory();
    factory.setLocation("/app/pttms/tmp");
    return factory.createMultipartConfig();
}

 

上一篇:Feign 接口上传文件


下一篇:MultipartFile文件编码判断