diff --git a/jpro-file/src/main/java/one/jpro/platform/file/util/SaveUtils.java b/jpro-file/src/main/java/one/jpro/platform/file/util/SaveUtils.java index aa116a8a..070e3821 100644 --- a/jpro-file/src/main/java/one/jpro/platform/file/util/SaveUtils.java +++ b/jpro-file/src/main/java/one/jpro/platform/file/util/SaveUtils.java @@ -5,6 +5,9 @@ import javafx.stage.FileChooser; import javafx.stage.Stage; import one.jpro.platform.file.ExtensionFilter; +import one.jpro.platform.file.FileStorage; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -26,38 +29,45 @@ public interface SaveUtils { * Saves a file using the provided save function. * This method should be used only for desktop/native applications. * - * @param fileToSave the file to be saved - * @param fileType the file extension to be appended to the file name if it does not already have it + * @param fileToSave the file to be saved + * @param fileType the file extension to be appended to the file name if it does not already have it * @param saveFunction the save function to be used to save the file * @return a CompletableFuture representing the asynchronous operation of saving the file * @throws NullPointerException if the fileToSave parameter is null */ - static CompletableFuture save(File fileToSave, String fileType, - Function> saveFunction) { + static CompletableFuture save(@NotNull final File fileToSave, + @Nullable String fileType, + @NotNull final Function> saveFunction) { Objects.requireNonNull(fileToSave, "File to save to cannot be null"); + if (fileType == null) { + fileType = ""; + } String filePath = fileToSave.getAbsolutePath(); - if (!filePath.endsWith(fileType)) { - fileToSave = new File(filePath + fileType); + final int lastDotIndex = filePath.lastIndexOf("."); + if (lastDotIndex > 0) { + filePath = filePath.substring(0, lastDotIndex) + fileType; } - return saveFunction.apply(fileToSave); + return saveFunction.apply(new File(filePath)); } /** * Saves a file with the given name and type using the provided save function. * This method should be used only for desktop/native applications. * - * @param stage The stage where the save dialog will be shown. - * @param fileName The initial file name. - * @param fileType The file type (extension) of the file to save. + * @param stage The stage where the save dialog will be shown. + * @param fileName The initial file name. + * @param fileType The file type (extension) of the file to save. * @param saveFunction The function to be called to save the file. This function takes a File parameter - * representing the file to save and returns a {@link CompletableFuture} that will - * complete with the saved file. + * representing the file to save and returns a {@link CompletableFuture} that will + * complete with the saved file. * @return A {@link CompletableFuture} that will complete with the saved file if the user selects a file - * to save, or fail with a NullPointerException if the user cancels the save operation. + * to save, or fail with a NullPointerException if the user cancels the save operation. */ - static CompletableFuture saveAs(Stage stage, String fileName, String fileType, - Function> saveFunction) { + static CompletableFuture saveAs(@NotNull final Stage stage, + @NotNull final String fileName, + @Nullable final String fileType, + @NotNull final Function> saveFunction) { final FileChooser fileChooser = new FileChooser(); fileChooser.setTitle("Save file as..."); @@ -88,20 +98,45 @@ static CompletableFuture saveAs(Stage stage, String fileName, String fileT * representing the file to save and returns a {@link CompletableFuture} that will * complete with the saved file. * @return A {@link CompletableFuture} that will complete with the downloaded file if the download is successful, - * or fail with an exception if the download fails or if the operation is not supported in the current environment. + * or fail with an exception if the download fails or if the operation is not supported in the current environment. + * @throws UnsupportedOperationException If the download operation is not supported in the current environment. + */ + static CompletableFuture download(@NotNull final Stage stage, + @NotNull final String fileName, + @Nullable final String fileType, + @NotNull final Function> saveFunction) throws IOException { + return download(stage, FileStorage.JPRO_TMP_DIR.toFile(), fileName, fileType, saveFunction); + } + + /** + * Downloads a file with the given name and type using the provided save function. + * + * @param stage The stage is needed to initialise the WebAPI. + * This is required to show the download dialog in a browser environment. + * @param tmpDir The temporary directory where the file will be saved before being offered for download. + * @param fileName The name of the file to be downloaded. + * @param fileType The file type (extension) of the file to be downloaded. + * @param saveFunction The function to be called to save the file. This function takes a File parameter + * representing the file to save and returns a {@link CompletableFuture} that will + * complete with the saved file. + * @return A {@link CompletableFuture} that will complete with the downloaded file if the download is successful, + * or fail with an exception if the download fails or if the operation is not supported in the current environment. * @throws UnsupportedOperationException If the download operation is not supported in the current environment. */ - static CompletableFuture download(Stage stage, String fileName, String fileType, - Function> saveFunction) { + static CompletableFuture download(@NotNull final Stage stage, + @NotNull final File tmpDir, + @NotNull final String fileName, + @Nullable final String fileType, + @NotNull final Function> saveFunction) throws IOException { if (WebAPI.isBrowser()) { WebAPI webAPI = WebAPI.getWebAPI(stage); final Logger logger = LoggerFactory.getLogger(SaveUtils.class); - final File tempFile = createTempFile(fileName, fileType); - return saveFunction.apply(tempFile).thenCompose(file -> { + final File tempFile = FileStorage.createTempFile(tmpDir.toPath(), fileName, fileType).toFile(); + return saveFunction.apply(tempFile).thenCompose(nothing -> { try { - final URL fileUrl = file.toURI().toURL(); - Platform.runLater(() -> webAPI.downloadURL(fileUrl, file::delete)); - return CompletableFuture.completedFuture(file); + final URL fileUrl = tempFile.toURI().toURL(); + Platform.runLater(() -> webAPI.downloadURL(fileUrl, tempFile::delete)); + return CompletableFuture.completedFuture(tempFile); } catch (IOException ex) { return CompletableFuture.failedFuture(ex); } @@ -116,24 +151,4 @@ static CompletableFuture download(Stage stage, String fileName, String fil throw new UnsupportedOperationException("Download is only supported in the browser"); } } - - /** - * Creates a temporary file with the given file name and file type. - * - * @param fileName The name of the file. - * @param fileType The file type (extension) of the file. - * @return A {@link File} object representing the created temporary file. - */ - static File createTempFile(String fileName, String fileType) { - // Get user home directory - final File tempDir = new File(System.getProperty("user.home") + "/.jpro/tmp"); - if (!tempDir.exists()) { - tempDir.mkdirs(); - } - String fullFileName = fileName; - if (!fullFileName.endsWith(fileType)) { - fullFileName = fullFileName.substring(0, fullFileName.lastIndexOf('.')) + fileType; - } - return new File(tempDir, fullFileName); - } }