从1.2.x迁移后,Spring boot 1.3.x MultipartFile.transferTo为null

时间:2016-01-13 14:14:44

标签: spring-boot embedded-jetty jetty-9

从Spring Boot 1.2.7升级到1.3.1后,我面临错误MultipartFile错误一天。

我注意到默认情况是现在是Jetty 9.2而不再是Tomcat 8.在我尝试使用MultipartFile.transferTo(File file)方法编写上传文件之前,一切都很好。

MultipartFile.transferTo()方法正在调用javax.servlet.http.Part的实现,这是以tomcat 8的方式实现的

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

这种方式适用于码头9.2

    public void write(String fileName) throws IOException
    {
        if (_file == null)
        {
            _temporary = false;

            //part data is only in the ByteArrayOutputStream and never been written to disk
            _file = new File (_tmpDir, fileName);

            BufferedOutputStream bos = null;
            try
            {
                bos = new BufferedOutputStream(new FileOutputStream(_file));
                _bout.writeTo(bos);
                bos.flush();
            }
            finally
            {
                if (bos != null)
                    bos.close();
                _bout = null;
            }
        }
        else
        {
            //the part data is already written to a temporary file, just rename it
            _temporary = false;

            File f = new File(_tmpDir, fileName);
            if (_file.renameTo(f))
                _file = f;
        }
    }

Jetty实现的错误在于等待文件名File.getName(),而不是File.getPath()

调用提供的绝对路径名StandardMultipartHttpServletRequest.transferTo(File file)
    @Override
    public void transferTo(File dest) throws IOException, IllegalStateException {
        this.part.write(dest.getPath());
    }

这是一个错误吗?请注意,这是因为我已从spring boot 1.2.7升级到1.3.1。默认是Tomcat,现在它是Jetty ......

2 个答案:

答案 0 :(得分:2)

根据javax.servlet.http.Part.write(String filename)的javadoc,filename参数是......

  

相对于中指定的位置创建文件   MultipartConfig

在Jetty 9.2中引用的代码中,即这个......

jetty-9.2.14.v20151106 - MultiPartInputStreamParser.write(String fileName)

您会看到它有两个可能的代码路径,第一个是内存中的""路径,第二个是'#34;磁盘上的文件"方法

在这两种情况下,当您指定Part.write(String)的文件名时,该名称相对于您的MultiPartConfig.location(您的问题中未详细说明的配置)。

MultiPartInputStreamParser的实施有一个_tmpDir which is configured from the webapp's MultiPartConfig.location

如果您希望此操作正常,强烈建议您定义适合您的应用程序的MultiPartConfig.location,而不是依靠容器来选择一个。

Part.write(String)中允许绝对文件名的Tomcat方法实际上不允许在servlet规范中(主要是因为它可以用来对系统造成破坏的安全问题)

答案 1 :(得分:0)

好的,目前如果你想摆脱这个错误,你可以切换回Tomcat而不是Jetty。

将tomcat放入您的依赖项中:

compile('org.springframework.boot:spring-boot-starter-tomcat')

并将tomcat声明为容器:

@Bean
public TomcatEmbeddedServletContainerFactory tomcatEmbeddedServletContainerFactory() {
    return new TomcatEmbeddedServletContainerFactory();
}