This is an automated email from the ASF dual-hosted git repository.
markt pushed a commit to branch 11.0.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git
The following commit(s) were added to refs/heads/11.0.x by this push:
new 1cdf5f730e Explicitly clean up after failed multi-part upload
1cdf5f730e is described below
commit 1cdf5f730ede75a0759492f179ac21ca4ff68e06
Author: Mark Thomas <[email protected]>
AuthorDate: Mon Sep 29 17:50:43 2025 +0100
Explicitly clean up after failed multi-part upload
---
.../catalina/connector/LocalStrings.properties | 1 +
java/org/apache/catalina/connector/Request.java | 23 +++++++++++++++++++++-
webapps/docs/changelog.xml | 4 ++++
3 files changed, 27 insertions(+), 1 deletion(-)
diff --git a/java/org/apache/catalina/connector/LocalStrings.properties
b/java/org/apache/catalina/connector/LocalStrings.properties
index 211566bea6..ac20c513aa 100644
--- a/java/org/apache/catalina/connector/LocalStrings.properties
+++ b/java/org/apache/catalina/connector/LocalStrings.properties
@@ -95,6 +95,7 @@ request.asyncNotSupported=A filter or servlet of the current
chain does not supp
request.fragmentInDispatchPath=The fragment in dispatch path [{0}] has been
removed
request.illegalWrap=The request wrapper must wrap the request obtained from
getRequest()
request.notAsync=It is illegal to call this method if the current request is
not in asynchronous mode (i.e. isAsyncStarted() returns false)
+request.partCleanup.failed=Unable to delete temporary file for uploaded part
after multi-part processing failed
request.session.failed=Failed to load session [{0}] due to [{1}]
requestFacade.nullRequest=The request object has been recycled and is no
longer associated with this facade
diff --git a/java/org/apache/catalina/connector/Request.java
b/java/org/apache/catalina/connector/Request.java
index 420a6b5c74..9e74406111 100644
--- a/java/org/apache/catalina/connector/Request.java
+++ b/java/org/apache/catalina/connector/Request.java
@@ -2570,8 +2570,10 @@ public class Request implements HttpServletRequest {
upload.setFileCountMax(partLimit);
parts = new ArrayList<>();
+ List<FileItem> items = null;
+ boolean success = false;
try {
- List<FileItem> items = upload.parseRequest(new
ServletRequestContext(this));
+ items = upload.parseRequest(new ServletRequestContext(this));
int maxPostSize = getConnector().getMaxPostSize();
long postSize = 0;
Charset charset = getCharset();
@@ -2607,6 +2609,7 @@ public class Request implements HttpServletRequest {
}
parts.add(part);
}
+ success = true;
} catch (InvalidContentTypeException e) {
partsParseException = new ServletException(e);
} catch (SizeException | FileCountLimitExceededException e) {
@@ -2617,6 +2620,24 @@ public class Request implements HttpServletRequest {
} catch (IllegalStateException e) {
checkSwallowInput();
partsParseException = e;
+ } finally {
+ /*
+ * GC will delete any temporary copies of uploaded files left in
the work directory but if we know that the
+ * upload has failed then explicitly clean up now.
+ */
+ if (!success) {
+ parts.clear();
+ if (items != null) {
+ for (FileItem item : items) {
+ try {
+ item.delete();
+ } catch (Throwable t) {
+ ExceptionUtils.handleThrowable(t);
+
log.warn(sm.getString("request.partCleanup.failed"), t);
+ }
+ }
+ }
+ }
}
}
diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
index 2e362f42dd..5970dd4d57 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -131,6 +131,10 @@
<fix>
Fix a case-sensitivity issue in the trailer header allow list. (markt)
</fix>
+ <fix>
+ Be proactive in cleaning up temporary files after a failed multi-part
+ upload rather than waiting for GC to do it. (markt)
+ </fix>
</changelog>
</subsection>
<subsection name="Coyote">
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]