mirror of
https://github.com/apache/struts.git
synced 2026-08-05 14:47:09 +00:00
WW-5573 Catches IO exception when a file cannot be deleted and reports it
This commit is contained in:
+15
@@ -38,6 +38,7 @@ import org.apache.struts2.inject.Inject;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
@@ -481,4 +482,18 @@ public abstract class AbstractMultiPartRequest implements MultiPartRequest {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete file if exists, reports warning if file cannot be deleted
|
||||
*
|
||||
* @param filePath a file to delete
|
||||
*/
|
||||
protected void deleteFile(Path filePath) {
|
||||
if (Files.exists(filePath)) {
|
||||
try {
|
||||
Files.delete(filePath);
|
||||
} catch (IOException e) {
|
||||
LOG.warn("Failed to delete file: {}", filePath, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-10
@@ -291,9 +291,7 @@ public class JakartaMultiPartRequest extends AbstractMultiPartRequest {
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("Cleaning up disk item: {} at {}", normalizeSpace(item.getFieldName()), itemPath);
|
||||
}
|
||||
if (Files.exists(itemPath) && !Files.deleteIfExists(itemPath)) {
|
||||
LOG.warn("There was a problem attempting to delete uploaded file: {}", itemPath);
|
||||
}
|
||||
deleteFile(itemPath);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LOG.warn("Error cleaning up DiskFileItem: {}", normalizeSpace(item.getFieldName()), e);
|
||||
@@ -327,13 +325,7 @@ public class JakartaMultiPartRequest extends AbstractMultiPartRequest {
|
||||
protected void cleanUpTemporaryFiles() {
|
||||
LOG.debug("Cleaning up {} temporary files created for in-memory uploads", temporaryFiles.size());
|
||||
for (File tempFile : temporaryFiles) {
|
||||
try {
|
||||
if (Files.exists(tempFile.toPath()) && !Files.deleteIfExists(tempFile.toPath())) {
|
||||
LOG.warn("There was a problem attempting to delete temporary file: {}", tempFile.getAbsolutePath());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LOG.warn("Error cleaning up temporary file: {}", tempFile.getAbsolutePath(), e);
|
||||
}
|
||||
deleteFile(tempFile.toPath());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+18
-20
@@ -82,11 +82,11 @@ public class JakartaStreamMultiPartRequest extends AbstractMultiPartRequest {
|
||||
|
||||
/**
|
||||
* Reads the entire contents of an input stream into a string.
|
||||
*
|
||||
*
|
||||
* <p>This method uses a buffered approach to efficiently read the stream
|
||||
* content without loading the entire stream into memory at once. It uses
|
||||
* try-with-resources to ensure proper cleanup of resources.</p>
|
||||
*
|
||||
*
|
||||
* @param inputStream the input stream to read from
|
||||
* @return the stream contents as a UTF-8 string
|
||||
* @throws IOException if an error occurs reading the stream
|
||||
@@ -106,7 +106,7 @@ public class JakartaStreamMultiPartRequest extends AbstractMultiPartRequest {
|
||||
|
||||
/**
|
||||
* Processes a normal form field (non-file) from the multipart request using streaming API.
|
||||
*
|
||||
*
|
||||
* <p>This method handles text form fields by:</p>
|
||||
* <ol>
|
||||
* <li>Validating the field name is not null</li>
|
||||
@@ -114,10 +114,10 @@ public class JakartaStreamMultiPartRequest extends AbstractMultiPartRequest {
|
||||
* <li>Checking if the field value exceeds maximum string length</li>
|
||||
* <li>Adding the value to the parameters collection</li>
|
||||
* </ol>
|
||||
*
|
||||
*
|
||||
* <p>Fields with null names are skipped with a warning log message.</p>
|
||||
* <p>The streaming approach is more memory-efficient for large form data.</p>
|
||||
*
|
||||
*
|
||||
* @param fileItemInput a form field item input from the streaming API
|
||||
* @throws IOException if an error occurs reading the input stream
|
||||
* @see #readStream(InputStream)
|
||||
@@ -129,7 +129,7 @@ public class JakartaStreamMultiPartRequest extends AbstractMultiPartRequest {
|
||||
LOG.warn("Form field has null fieldName, skipping");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
String fieldValue = readStream(fileItemInput.getInputStream());
|
||||
if (exceedsMaxStringLength(fieldName, fieldValue)) {
|
||||
return;
|
||||
@@ -191,7 +191,7 @@ public class JakartaStreamMultiPartRequest extends AbstractMultiPartRequest {
|
||||
|
||||
/**
|
||||
* Processes a file field from the multipart request using streaming API.
|
||||
*
|
||||
*
|
||||
* <p>This method handles file uploads by:</p>
|
||||
* <ol>
|
||||
* <li>Validating the file name and field name are not null/empty</li>
|
||||
@@ -201,13 +201,13 @@ public class JakartaStreamMultiPartRequest extends AbstractMultiPartRequest {
|
||||
* <li>Checking if the total size exceeds maximum allowed size</li>
|
||||
* <li>Creating an {@link UploadedFile} abstraction or cleaning up on size exceeded</li>
|
||||
* </ol>
|
||||
*
|
||||
*
|
||||
* <p>Files with null names or field names are skipped with appropriate logging.</p>
|
||||
* <p>The streaming approach is more memory-efficient for large file uploads
|
||||
* as it writes directly to disk rather than loading into memory first.</p>
|
||||
*
|
||||
*
|
||||
* @param fileItemInput file item representing upload file from streaming API
|
||||
* @param location the directory where temporary files will be created
|
||||
* @param location the directory where temporary files will be created
|
||||
* @throws IOException if an error occurs during file processing
|
||||
* @see #createTemporaryFile(String, Path)
|
||||
* @see #streamFileToDisk(FileItemInput, File)
|
||||
@@ -219,7 +219,7 @@ public class JakartaStreamMultiPartRequest extends AbstractMultiPartRequest {
|
||||
LOG.debug(() -> "No file has been uploaded for the field: " + normalizeSpace(fileItemInput.getFieldName()));
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Skip file uploads that don't have a field name
|
||||
if (fileItemInput.getFieldName() == null) {
|
||||
LOG.warn("File upload has null fieldName, skipping");
|
||||
@@ -232,13 +232,11 @@ public class JakartaStreamMultiPartRequest extends AbstractMultiPartRequest {
|
||||
|
||||
File file = createTemporaryFile(fileItemInput.getName(), location);
|
||||
streamFileToDisk(fileItemInput, file);
|
||||
|
||||
|
||||
// Reject empty files (0 bytes) as they are not considered valid uploads
|
||||
if (rejectEmptyFile(file.length(), fileItemInput.getName(), fileItemInput.getFieldName())) {
|
||||
// Clean up the empty temporary file
|
||||
if (Files.exists(file.toPath()) && !Files.deleteIfExists(file.toPath())) {
|
||||
LOG.warn("Failed to delete empty temporary file: {}", file.getAbsolutePath());
|
||||
}
|
||||
deleteFile(file.toPath());
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -269,7 +267,7 @@ public class JakartaStreamMultiPartRequest extends AbstractMultiPartRequest {
|
||||
|
||||
/**
|
||||
* Creates an {@link UploadedFile} abstraction over an uploaded file.
|
||||
*
|
||||
*
|
||||
* <p>This method creates a wrapper around the uploaded file that provides
|
||||
* a consistent interface for accessing file information and content.
|
||||
* The created {@link UploadedFile} instance contains:</p>
|
||||
@@ -279,19 +277,19 @@ public class JakartaStreamMultiPartRequest extends AbstractMultiPartRequest {
|
||||
* <li>The form field name that contained the file</li>
|
||||
* <li>A reference to the temporary file on disk</li>
|
||||
* </ul>
|
||||
*
|
||||
*
|
||||
* <p>The file is automatically added to the uploaded files collection,
|
||||
* grouped by field name to support multiple file uploads per field.</p>
|
||||
*
|
||||
*
|
||||
* @param fileItemInput file item stream containing file metadata
|
||||
* @param file the temporary file containing the uploaded content
|
||||
* @param file the temporary file containing the uploaded content
|
||||
* @see UploadedFile
|
||||
* @see StrutsUploadedFile
|
||||
*/
|
||||
protected void createUploadedFile(FileItemInput fileItemInput, File file) {
|
||||
String fileName = fileItemInput.getName();
|
||||
String fieldName = fileItemInput.getFieldName();
|
||||
|
||||
|
||||
// fieldName null check already done in processFileItemAsFileField
|
||||
UploadedFile uploadedFile = StrutsUploadedFile.Builder
|
||||
.create(file)
|
||||
|
||||
Reference in New Issue
Block a user