Spring 引导 1.3.x MultipartFile.transferTo 从 1.2.x 迁移后为空
Spring boot 1.3.x MultipartFile.transferTo null after migration from 1.2.x
从 Spring Boot 1.2.7 升级到 1.3.1 后一天,我遇到了 MultipartFile 错误。
我注意到现在默认是 Jetty 9.2,不再是 Tomcat8。一切都很好,直到我尝试使用 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()
而不是 StandardMultipartHttpServletRequest.transferTo(File file)
[=23= 的调用提供的绝对路径名 File.getPath()
]
@Override
public void transferTo(File dest) throws IOException, IllegalStateException {
this.part.write(dest.getPath());
}
这是一个错误吗?请注意,这是因为我已从 spring boot 1.2.7 升级到 1.3.1。默认是 Tomcat,现在是 Jetty...
好的,目前如果你想摆脱这个错误,你可以切换回 Tomcat 而不是 Jetty。
将 tomcat 放入您的依赖项中:
compile('org.springframework.boot:spring-boot-starter-tomcat')
并声明 tomcat 为容器:
@Bean
public TomcatEmbeddedServletContainerFactory tomcatEmbeddedServletContainerFactory() {
return new TomcatEmbeddedServletContainerFactory();
}
根据 javax.servlet.http.Part.write(String filename)
的 javadoc,filename
参数是 ...
The file is created relative to the location as specified in the
MultipartConfig
在您在 Jetty 9.2 中引用的代码中,即这个...
jetty-9.2.14.v20151106 - MultiPartInputStreamParser.write(String fileName)
您会看到它有 2 种可能的代码路径,第一个是 "in memory" 路径,第二个是 "file on disk" 方法。
在这两种情况下,当您为 Part.write(String)
指定一个文件名时,该名称是相对于您的 MultiPartConfig.location
(您在问题中没有详细说明的配置)。
MultiPartInputStreamParser
的实现有一个 _tmpDir
which is configured from the webapp's MultiPartConfig.location
。
如果您希望它正常运行,强烈建议您定义一个适合您的应用程序的 MultiPartConfig.location
,而不是依赖容器来选择一个。
允许在 Part.write(String)
中使用绝对文件名的 Tomcat 方法在 servlet 规范中实际上是不允许的(主要是因为它是一个安全问题,可用于对系统造成严重破坏)
从 Spring Boot 1.2.7 升级到 1.3.1 后一天,我遇到了 MultipartFile 错误。
我注意到现在默认是 Jetty 9.2,不再是 Tomcat8。一切都很好,直到我尝试使用 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()
而不是 StandardMultipartHttpServletRequest.transferTo(File file)
[=23= 的调用提供的绝对路径名 File.getPath()
]
@Override
public void transferTo(File dest) throws IOException, IllegalStateException {
this.part.write(dest.getPath());
}
这是一个错误吗?请注意,这是因为我已从 spring boot 1.2.7 升级到 1.3.1。默认是 Tomcat,现在是 Jetty...
好的,目前如果你想摆脱这个错误,你可以切换回 Tomcat 而不是 Jetty。
将 tomcat 放入您的依赖项中:
compile('org.springframework.boot:spring-boot-starter-tomcat')
并声明 tomcat 为容器:
@Bean
public TomcatEmbeddedServletContainerFactory tomcatEmbeddedServletContainerFactory() {
return new TomcatEmbeddedServletContainerFactory();
}
根据 javax.servlet.http.Part.write(String filename)
的 javadoc,filename
参数是 ...
The file is created relative to the location as specified in the MultipartConfig
在您在 Jetty 9.2 中引用的代码中,即这个...
jetty-9.2.14.v20151106 - MultiPartInputStreamParser.write(String fileName)
您会看到它有 2 种可能的代码路径,第一个是 "in memory" 路径,第二个是 "file on disk" 方法。
在这两种情况下,当您为 Part.write(String)
指定一个文件名时,该名称是相对于您的 MultiPartConfig.location
(您在问题中没有详细说明的配置)。
MultiPartInputStreamParser
的实现有一个 _tmpDir
which is configured from the webapp's MultiPartConfig.location
。
如果您希望它正常运行,强烈建议您定义一个适合您的应用程序的 MultiPartConfig.location
,而不是依赖容器来选择一个。
允许在 Part.write(String)
中使用绝对文件名的 Tomcat 方法在 servlet 规范中实际上是不允许的(主要是因为它是一个安全问题,可用于对系统造成严重破坏)