mirror of
https://github.com/Frooodle/Stirling-PDF.git
synced 2025-09-08 17:51:20 +02:00
fix: try-with-resources for Streams interacting with Files to ensure proper resource management (#4404)
# Description of Changes The Javadoc recommends wrapping Files.list(), Files.walk(), Files.find(), and Files.lines() in try-with-resources so the stream’s close() is called as soon as the terminal operation completes. This is because when Stream interact with files, Java can ONLY close the Stream during garbage-collection finalization, which is not guaranteed to run promptly or at all before the JVM exits, creating a memory leak. Direct quote: > Streams have a [BaseStream.close()](https://docs.oracle.com/javase/8/docs/api/java/util/stream/BaseStream.html#close--) method and implement [AutoCloseable](https://docs.oracle.com/javase/8/docs/api/java/lang/AutoCloseable.html), but nearly all stream instances do not actually need to be closed after use. Generally, only streams whose source is an IO channel (such as those returned by [Files.lines(Path, Charset)](https://docs.oracle.com/javase/8/docs/api/java/nio/file/Files.html#lines-java.nio.file.Path-java.nio.charset.Charset-)) will require closing. Most streams are backed by collections, arrays, or generating functions, which require no special resource management. (If a stream does require closing, it can be declared as a resource in a try-with-resources statement.) > A DirectoryStream is opened upon creation and is closed by invoking the close method. Closing a directory stream releases any resources associated with the stream. Failure to close the stream may result in a resource leak. The try-with-resources statement provides a useful construct to ensure that the stream is closed: Sources: https://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/nio/file/DirectoryStream.html https://stackoverflow.com/questions/79078272/using-try-with-resources-for-a-java-files-walk-stream-created-in-a-separate-meth https://stackoverflow.com/questions/36990053/resource-leak-in-files-listpath-dir-when-stream-is-not-explicitly-closed <!-- Please provide a summary of the changes, including: - What was changed - Why the change was made - Any challenges encountered Closes #(issue_number) --> --- ## Checklist ### General - [x] I have read the [Contribution Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md) - [x] I have read the [Stirling-PDF Developer Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/DeveloperGuide.md) (if applicable) - [ ] I have read the [How to add new languages to Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md) (if applicable) - [x] I have performed a self-review of my own code - [x] My changes generate no new warnings ### Documentation - [ ] I have updated relevant docs on [Stirling-PDF's doc repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/) (if functionality has heavily changed) - [ ] I have read the section [Add New Translation Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags) (for new translation tags only) ### UI Changes (if applicable) - [ ] Screenshots or videos demonstrating the UI changes are attached (e.g., as comments or direct attachments in the PR) ### Testing (if applicable) - [x] I have tested my changes locally. Refer to the [Testing Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/DeveloperGuide.md#6-testing) for more details. --------- Signed-off-by: Balázs Szücs <bszucs1209@gmail.com>
This commit is contained in:
parent
5e72dce0de
commit
47bce86ae2
@ -124,8 +124,8 @@ public class FileToPdf {
|
||||
private static void zipDirectory(Path sourceDir, Path zipFilePath) throws IOException {
|
||||
try (ZipOutputStream zos =
|
||||
new ZipOutputStream(new FileOutputStream(zipFilePath.toFile()))) {
|
||||
Files.walk(sourceDir)
|
||||
.filter(path -> !Files.isDirectory(path))
|
||||
try (Stream<Path> walk = Files.walk(sourceDir)) {
|
||||
walk.filter(path -> !Files.isDirectory(path))
|
||||
.forEach(
|
||||
path -> {
|
||||
ZipEntry zipEntry =
|
||||
@ -140,6 +140,7 @@ public class FileToPdf {
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void deleteDirectory(Path dir) throws IOException {
|
||||
Files.walkFileTree(
|
||||
|
@ -9,6 +9,7 @@ import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Stream;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
@ -150,10 +151,11 @@ public class ConvertImgPDFController {
|
||||
.runCommandWithOutputHandling(command);
|
||||
|
||||
// Find all WebP files in the output directory
|
||||
List<Path> webpFiles =
|
||||
Files.walk(tempOutputDir)
|
||||
.filter(path -> path.toString().endsWith(".webp"))
|
||||
.toList();
|
||||
List<Path> webpFiles;
|
||||
try (Stream<Path> walkStream = Files.walk(tempOutputDir)) {
|
||||
webpFiles =
|
||||
walkStream.filter(path -> path.toString().endsWith(".webp")).toList();
|
||||
}
|
||||
|
||||
if (webpFiles.isEmpty()) {
|
||||
log.error("No WebP files were created in: {}", tempOutputDir.toString());
|
||||
|
@ -48,10 +48,12 @@ public class FilterController {
|
||||
String text = request.getText();
|
||||
String pageNumber = request.getPageNumbers();
|
||||
|
||||
PDDocument pdfDocument = pdfDocumentFactory.load(inputFile);
|
||||
if (PdfUtils.hasText(pdfDocument, pageNumber, text))
|
||||
try (PDDocument pdfDocument = pdfDocumentFactory.load(inputFile)) {
|
||||
if (PdfUtils.hasText(pdfDocument, pageNumber, text)) {
|
||||
return WebResponseUtils.pdfDocToWebResponse(
|
||||
pdfDocument, Filenames.toSimpleFileName(inputFile.getOriginalFilename()));
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -8,6 +8,7 @@ import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.stream.Stream;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
@ -142,7 +143,10 @@ public class ExtractImageScansController {
|
||||
.runCommandWithOutputHandling(command);
|
||||
|
||||
// Read the output photos in temp directory
|
||||
List<Path> tempOutputFiles = Files.list(tempDir).sorted().toList();
|
||||
List<Path> tempOutputFiles;
|
||||
try (Stream<Path> listStream = Files.list(tempDir)) {
|
||||
tempOutputFiles = listStream.sorted().toList();
|
||||
}
|
||||
for (Path tempOutputFile : tempOutputFiles) {
|
||||
byte[] imageBytes = Files.readAllBytes(tempOutputFile);
|
||||
processedImageBytes.add(imageBytes);
|
||||
|
@ -7,6 +7,7 @@ import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.thymeleaf.util.StringUtils;
|
||||
@ -66,11 +67,12 @@ public class SignatureService {
|
||||
|
||||
private List<SignatureFile> getSignaturesFromFolder(Path folder, String category)
|
||||
throws IOException {
|
||||
return Files.list(folder)
|
||||
.filter(path -> isImageFile(path))
|
||||
try (Stream<Path> stream = Files.list(folder)) {
|
||||
return stream.filter(this::isImageFile)
|
||||
.map(path -> new SignatureFile(path.getFileName().toString(), category))
|
||||
.toList();
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] getSignatureBytes(String username, String fileName) throws IOException {
|
||||
validateFileName(fileName);
|
||||
|
Loading…
Reference in New Issue
Block a user