so as the title of the post states I'm asking for a way that I can say a file I uploaded using FileChooser to a directory in my project.
More specifically, I'm uploading images and I want to save them in my project so I can use them in the future. Here is an example code:
Controller:
package org.example;
import javafx.fxml.FXML;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.stage.FileChooser;
import java.io.File;
public class PrimaryController {
@FXML
private ImageView image;
@FXML
void handleUploadImage() {
FileChooser fileChooser = new FileChooser();
fileChooser.getExtensionFilters().addAll(new FileChooser.ExtensionFilter("Image Files", "*.jpg", "*.jpeg", "*.png", "*.svg"));
File file = fileChooser.showOpenDialog(null);
if (file != null) {
image.setImage(new Image(String.valueOf(file)));
} else {
System.out.println("It's null");
}
}
}
FXML:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.Cursor?>
<?import javafx.scene.image.Image?>
<?import javafx.scene.image.ImageView?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" style="-fx-background-color: linear-gradient(to right, #1c92d2, #f2fcfe);" xmlns="http://javafx.com/javafx/18" xmlns:fx="http://javafx.com/fxml/1" fx:controller="org.example.PrimaryController">
<children>
<ImageView fx:id="image" fitHeight="200.0" fitWidth="200.0" layoutX="200.0" layoutY="100.0" onm ouseClicked="#handleUploadImage" pickOnBounds="true" preserveRatio="true">
<image>
<Image url="@../../images/upload.png" />
</image>
<cursor>
<Cursor fx:constant="HAND" />
</cursor>
</ImageView>
</children>
</AnchorPane>
My directories:
I would like to save the image in /resources/images
. How can I do so?
CodePudding user response:
Background Info
The file is not being "uploaded". That term is usually for an operation such as sending a file to a hosted cloud service or FTP site. Your code chooses a file available through the local machine's file system. Then you want to do something with it. Probably copy it to another location locally. I guess you might choose to cause that process "uploaded", but, to me, that term doesn't really seem to fit well.
Normally, when a JavaFX application is deployed, all of its code and resources will be packaged together, e.g. in a jar file, installer, or jlink image. The resources directory of your project source code will not be there, but the contents of it will have been copied into the package. To add additional resources to that location at runtime is an undefined operation as you don't really know where the resources will go.
Suggested Alternative: Save to known local file location
What you probably want to do is to copy the file to a well-known location on the machine and access it from there. One way to do that would be to create a directory (e.g. .myapp
) under the user's home directory, copy the chosen file into that directory and then read and write the file from there as needed. You can determine the user's home directory using java system properties.
FAQ
It doesn't really make any sense. What I must do then if I'm willing to allow the user to upload an image and then save the image somewhere on my pc or in my project?
Presumably, your "project" is the source code directory you show in your question. As noted, that directory is not available at runtime outside a local development environment. So you can't save the file to the project at runtime because it won't exist. Instead, you need to "save the image somewhere on my pc". One way to do that is by following the suggestion I provided regarding placing the image in an app-specific sub-directory that your application creates in the user's home directory.
Does this solution works globally? like the project isn't just for me meaning it'll be sent to some fellows so they won't have the directory I saved the file to.
They will have a user directory because that is how OSes work. That is available from the system properties I linked. If you go the route of your app creating and using an app-specific sub-directory under the user directory as needed, then you can be assured that the required directory will exist. There are other conventions on storage in OSes for different locations, but I'd really advise just using the app-specific directory under the user directory unless you need to do something else. There are other options such as uploading to a cloud hosting image service but don't do that unless you need it.
Plus, in the project I place all images I use in a directory that's existed in the directory which is for example /resources/images and I need to save the images in it.
As explained, you can't do that dynamically at runtime. You need to place the dynamically added images somewhere else (e.g. under the user local directory, cloud service, shared database, etc). And you need to read those files from the same place. If you place them under the user directory, then you can read and write the files using file URLs or file API rather than getResource.
CodePudding user response:
I got an answer to my question after many searches. In a conclusion, it was just like jewelsea explained but he didn't provide a code or a real good explanation for my question so here I provide an example code that may help:
FileChooser fileChooser = new FileChooser();
fileChooser.getExtensionFilters().addAll(new FileChooser.ExtensionFilter("Image Files", "*.jpg", "*.jpeg", "*.png"));
File file = fileChooser.showOpenDialog(null);
if (file != null) {
File file1 = new File(file.getAbsolutePath());
BufferedImage bufferedImage = ImageIO.read(file1);
String fileName = file.getName();
if (fileName.endsWith("png") || fileName.endsWith("jpg")) {
fileName = fileName.substring(fileName.length() - 3);
} else { // This is for .jpeg
fileName = fileName.substring(fileName.length() - 4);
}
String path = System.getProperty("user.dir") "\\src\\main\\resources\\Image\\" file.getName();
File file2 = new File(path);
ImageIO.write(bufferedImage, fileName, file2);
}
I save the image in my project in \src\main\resources\Image folder which I take photos from in the project. However, Note that after the file is added and as jewelsea explained the Stage has to be reloaded in order to apply changes because it won't recognize the file since it loaded the project before the file was added to it So according to it the file/image is not defined at the moment and it's treated as null.