临时上传位置[/tmp/tomcat.4296537502689403143.5000/work/Tomcat/localhost/ROOT]无效。

35

我正在使用Spring Boot 1.5.13版本。

我收到以下异常消息。

Could not parse multipart servlet request; nested exception is java.io.IOException: The temporary upload location [/tmp/tomcat.4296537502689403143.5000/work/Tomcat/localhost/ROOT] is not valid

我在Spring Github问题中发现了这个问题。 https://github.com/spring-projects/spring-boot/issues/9616

但我仍然有一些疑问。

  1. 我的应用程序中没有使用文件上传功能。但是日志显示“无法解析多部分servlet请求”,为什么会出现这种情况?(当我的应用程序使用RestTemplate(Post方法)时,我遇到了异常)
  2. 为了解决这个异常,我重新启动了我的应用程序,但它并没有立即起作用。尽管我重新启动了我的应用程序,但它引用了不存在的tomcat目录。在重新启动后的一天之后,它开始起作用了。我猜想该目录在Spring或其他地方被缓存了吗?

请帮帮我!

10个回答

42
  1. http的POST方法会使用这些临时位置来存储POST数据。
  2. 像CentOS这样的操作系统经常会删除临时目录。因此,即使您设置了该位置的权限,在一段时间后该目录也将被操作系统删除。而在重新启动后,临时目录将不同。

您可以在application.yml中设置multipart位置:

spring:
  http:
    multipart:
      location: /data/upload_tmp

更新

根据Vivek Sethi的评论,上述属性对我没有起作用,但下面这个可以。

spring.servlet.multipart.location=/data/upload_tmp

12
该属性已经过时。请使用spring.servlet.multipart.location代替。 - Vivek Sethi
3
如果有人想要指定一个非“tmp”位置,可以在我的application.yml中使用以下代码:spring.servlet.multipart.location: ${user.dir} - Vivek Sethi
3
spring.servlet.multipart.location 在 Spring Boot 1.5.9 上不起作用,但 spring.http.multipart.location 可以使用。 - Daniel Dai
@mavlarn,这只是一个临时解决方案,我们如何永久解决,即使它显示错误,找不到新位置。 - Deva
我认为这不是一个临时解决方案。我们需要确保我们的应用程序可以在不同的系统上运行。CentOS 有时会删除临时目录。因此,我们需要定义一个我们使用的临时目录位置。这样就不会受到系统对临时目录的行为影响。 - Mavlarn
我正在使用Spring Boot 1.5.9,并配置了spring.http.multipart.location=/upload,但是当我执行new File("/upload").canWrite()时仍然返回false,尽管我能够进行多部分文件上传,这是怎么可能的? - Dimitri Kopriwa

13

只需在服务器上重新启动您的应用程序。这是Spring和Tomcat服务器之间的错误。一旦应用程序重新启动,它会在服务器上使用一个临时目录。


2
如果在UAT或生产环境中出现错误怎么办?我们不能一遍又一遍地重启服务器。 - Deva
1
正如我之前提到的,这个问题的原因是 CentOS 经常会删除临时目录。当你的应用程序正在运行时,但是 CentOS 删除了你的临时目录,那么就会出现这样的错误。因此,重新启动你的应用程序可以暂时解决问题。但是过一段时间后,那个错误还是会出现。 - Mavlarn

7

6
我们长期以来一直存在这个问题,我只是想详细阐述一下与上面接受的答案中的2)相关的一些内容。
问题在于Tomcat的临时文件夹突然“消失”,并不是像声称的那样“总体上都会有POST问题”,而是针对特定的多部分请求。因此,spring.servlet.multipart.location/spring.http.multipart.location 在这里起作用。正如@Frankstar在上面所说的,在最近的Spring Boot代码中,通过“如果没有,始终创建tmp文件夹”的方式进行了修复,当然,如果你正在运行超级新的Spring Boot,则也可以正常工作。
就像接受的答案中建议的那样,您可以将其指向除了/tmp之外的其他位置,它将正常工作(但是关于清理,您应该阅读这里 https://github.com/spring-projects/spring-boot/issues/9983 - 现在您依赖于Spring Boot的清理,虽然理论上应该正常工作)。
但是为什么实际上文件夹会消失呢?下面@Hasan Sawan说“这是Spring和Tomcat服务器之间的错误”。但是真的吗..?
对我们来说,解决方案是配置这些东西。例如,CentOS等操作系统将使用(详见 https://www.thegeekdiary.com/centos-rhel-7-how-tmpfiles-clean-up-tmp-or-var-tmp-replacement-of-tmpwatch)systemd来清理/tmp - 默认设置将在10天内未被访问的任何内容进行清理。
因此,在我们的Red Hat服务器上,我们通过编辑配置文件来解决这个问题。
/usr/lib/tmpfiles.d/tmp.conf

添加一行类似于

X /tmp/tomcat.* 

为了解决这个问题,你也可以使用以下方法进行验证。
# SYSTEMD_LOG_TARGET=console SYSTEMD_LOG_LEVEL=debug /usr/bin/systemd-tmpfiles --clean 2>&1 | grep tomcat 

你将会看到这些目录现在已被忽略。

对于使用tmpwatch的系统,也有解决方法:https://javahotfix.blogspot.com/2019/03/spring-boot-micro-services-tmptomcat.html

注意:我工作的地方不接受上述“重新启动”或只是“# mkdir /tmp/tomcat...” 的解决方案。


2
问题已经得到解答,但也许我可以帮助其他人。我也遇到了这个问题,但是建议的解决方案都没有对我起作用。
我们使用Spring Boot与Zuul结合使用,步骤如下:
1. 停止应用程序 2. 停止Zuul 3. 删除/tmp文件夹中与tomcat相关的文件夹(我们的tomcat文件夹存储在此处,其他人可能不同) 4. 重新启动Zuul 5. 重新启动应用程序
仅仅重新启动应用程序并不能解决问题,因为它指向了一个不存在的文件夹:名称被缓存在某个地方。
当使用Zuul时,请求首先通过Zuul并在那里抛出异常。

同意,在微服务架构中,问题可能出现在Zuul上。我面对了同样的问题,并尝试了上面讨论的所有方法,但都没有奏效。在Zuul属性中使用dfs-bulk-service.ribbon.ReadTimeout = 90000配置增加超时时间后,问题得到了解决。 - Rajdeep
请注意,上述评论中的“dfs-bulk-service”是实际服务名称,对于您来说可能会有所不同。参考:https://cloud.spring.io/spring-cloud-netflix/multi/multi__router_and_filter_zuul.html - nanospeck

1
我解决这个问题的方法是重新启动应用程序并添加-java.tmp.dir=/path/to/application/temp/,同时在我的应用程序文件夹中创建一个/temp/文件夹。

0

如果在 C:/ 文件夹中没有名为temp的文件夹,请创建C:/temp,这个方法对我有用


0

您可以使用Content-Type:multipart/form-data http头编码POST请求的表单数据体。

您应该发送一个Content-Type:application/x-www-form-urlencoded POST请求。


0
在微服务架构中,问题可能是由于Zuul超时引起的。我遇到了同样的问题,尝试了上面讨论的所有方法,但都没有起作用。在Zuul属性中使用dfs-bulk-service.ribbon.ReadTimeout=90000配置增加超时时间后,它正常工作了。这里的dfs-bulk-service是我的微服务名称,已经配置为Zuul作为API网关。

请注意上面答案中的“dfs-bulk-service”是实际服务名称,您的名称可能不同。参考链接:https://cloud.spring.io/spring-cloud-netflix/multi/multi__router_and_filter_zuul.html - nanospeck

0

对我来说,关键是使用正确的依赖项(如果使用Java/Maven)

       <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.6</version>
        </dependency>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接