Testing for the existence of a resource given its relative URI - java

I wrote a little Java servlet that would dynamically generate an image button given parameters including label, height, width and so on, and it would add each new one to a cache. It worked fine, BUT it required a servlet call for every call to display the button or its highlighted version. I dumped the cache and made PNG files of all the buttons used at the moment in the app, added those files to the app so they could be referenced by "/images/button/xyz.png", where the filename is a hash of the input parameters.
That works fine, but I want my original servlet to be called on the occasion when someone has added a new button. I use a custom tag to define these buttons, so the tag handler gets called when the JSP compiles... so I have a point where I can choose to use one of the pre-generated buttons, OR generate a reference to the servlet so it can render the button when it is displayed.
My question is: How can I detect the image is available in pre-rendered for? I'm not sure that a call to create a URL object based off the full path and then doing a call to getResource() is the answer -- I don't want it to load the image at this time, I just need to know if it exists.
Is there some way to create a File object that would take a relative URI and allow me to test for existence?

I suppose you are talking about the getResource() method on java.lang.Class . This is actually well-suited to the problem since by contract, it will return null if no resource exists with the given path. The resource isn't actually loaded until you use getResourceAsStream() (or similar) so this is not a performance concern.

You can try the following approach in a utility class.
public static boolean imageExists(final String imageFileName) throws Exception{
boolean status = false;
HttpURLConnection conn = null;
URL url = new URL(imageFileName);
conn = (HttpURLConnection )url.openConnection();
conn.setRequestMethod("HEAD");
String contentType = conn.getContentType();
if(contentType.contains("image")){
status = true;
}else{
status = false;
}
return status;
}
This assumes your image file names are unique.

Related

JavaFX Image from resources folder

For some reason I keep getting an NPE in a gradle javafx project.
My folder structure is very basic. I have a package with my java files in the main/java folder. I also have my resources in the main/resources folder. When I try to load image.png it gives me an NPE.
public static Image createImage(Object context, String url) {
Image m = null;
InputStream str = null;
URL _url = context.getClass().getResource(url);
try {
m = new Image(_url.getPath());
} catch (NullPointerException e) {
e.printStackTrace();
}
return m;
}
This is a helper class.
From the Scene I call: Image image = Helper.createImage(this, "image.png");
The absolute path to the image would be main/resources/images/image.png.
I checked every tutorial on the internet but I couldn't find any solution for this. I also tried it with the path to the image as parameter and also with an InputStream but it never worked.
Resources
The Class#getResource(String) and related API are used for locating resources relative to the class path and/or module path. When using Class to get a resource you can pass an absolute name or a relative name. An absolute name will locate the resource relative to the root of the class path/module path; an absolute name starts with a /. A relative name will locate the resource relative to the location of the Class; a relative name does not start with a leading /.
In a typical Maven/Gradle project structure, the src/main/java and src/main/resources are roots of the class path/module path. This means all resource names are relative to those directories. It's slightly more complicated than that because the files under those directories are moved to the target/build directory and it's that location that's put on the class path/module path, but for all intents and purposes consider the source directories as the root. There's a reason a get-resource API exists in the first place, to provide an application-location-independent way of obtaining resources.
Issues in Your Code
From your question I gather your project structure looks something like:
<project-dir>
|--src/
|--main/
|--java/
|--resources/
|--images/
|--image.png
And you're calling your method with an Object and a resource name of image.png. The problem here is that, since you're passing a relative name, the resource is located relative to the Class of the passed Object (i.e. context). I doubt your class is located in a package named images which means the resource will not be found relative to said class. You need to pass an absolute name: /images/image.png.
The other problem is your use of URL#getPath(). The URL you obtain from Class#getResource(String) will, if the resource were to be found, look something like this:
file:/path/to/gradle/project/build/resources/main/images/image.png
But the result of URL#getPath() will give you:
/path/to/gradle/project/build/resources/main/images/image.png
This causes a problem due to the way Image works. From the documentation:
All URLs supported by URL can be passed to the constructor. If the passed string is not a valid URL, but a path instead, the Image is searched on the classpath in that case.
Notice the second sentence. If the passed URL does not have a scheme then it's interpreted as a resource name and the Image will locate the image file relative to the classpath. In other words, since you're passing the value of URL#getPath() to the Image constructor it searches for the resource image.png in the package path.to.gradle.project.build.resources.main.images. That package does not exist. You should be passing the URL as-is to the Image constructor via URL#toString() or URL#toExternalForm().
Solution
If you're going to use the URL returned by Class#getResource(String) to load the Image then no matter what you need to use URL#toString() or URL#toExternalForm() instead of URL#getPath().
public static Image createImage(Object context, String resourceName) {
URL _url = context.getClass().getResource(resourceName);
return new Image(_url.toExternalForm());
}
Then you have at least two options:
Pass the absolute resource name (i.e. "/images/image.png") to your #createImage(Object,String) method since the image.png resource is not in the same package as the passed Object (i.e. context).
Move the resource to the same package as the class of the passed in Object (i.e. context). For instance, if the context object's class is com.foo.MyObject then place the resource under src/main/resources/com/foo and it will be in the same package as MyObject. This will allow you to continue passing the relative resource name.
Of course, as noted by the documentation of Image you can pass a scheme-less URL and it's interpreted as a resource name. In other words, you could do:
Image image = new Image("images/image.png");
And that should work. A note of caution, however: When using modules the above will only work if the resource-containing package is opens unconditionally or if the module itself is open.
Try using the path /images/image.png.
The resources always get referenced from the class root, in your case src/main/resources, so from there going to /images/image.png should be the correct path.
this is how I am passing the images in my application. ivSerialAssignmentLogo is a FXML element (ImageView).
ivSerialAssignmentLogo.setImage(new Image(getClass().getResourceAsStream("/img/serialAssignment.svg")));
In your case, you could use something like that
public static Image createImage(Object context, String url) {
Image m = null;
InputStream str = null;
URL _url = context.getClass().getResource("/images/" + url);
try {
m = new Image(_url.getPath());
} catch (NullPointerException e) {
e.printStackTrace();
}
return m;
}

Adding/Loading an image in java

I am trying to load an image to display on the screen (just to get an idea of how to do it).
The problem is that when the program tries to load "apple.png" (which is saved on my desktop), it cannot find the image - Where do image files need to be stored in order for them to be found? Here is my loading method:
private void loadImage() {
ImageIcon appleIcon = new ImageIcon("apple.png");
Image appleImage = appleIcon.getImage();
}
If you want to reach it from the desktop, you should use the complete path. The easiest way to handle resources would be to create a folder in you java project, which you can access via "folderName/fileName.example".
Using the full path is an option
C:\filefolder\file.jpg
To answer your question though
Wherever your java file is is where it's going to think "home is" make yourself a java workspace to put your java source files in and inside it create a folder to put any assets you want in that way you will simply be able to call "apple.jpg"
if you want use the file name only, the file path ("apple.png")is relative to the source folder. so you have to place it in there.
you could also use absolute the file path to your desktop (sthg like "C:\Users\your.name\Desktop")
From the javadoc:
Creates an ImageIcon from the specified file. The image will be preloaded by using MediaTracker to monitor the loading state of the image. The specified String can be a file name or a file path. When specifying a path, use the Internet-standard forward-slash ("/") as a separator. (The string is converted to an URL, so the forward-slash works on all systems.) For example, specify:
new ImageIcon("images/myImage.gif")
As #Shriram mentioned, when you only specify the filename (with extension), it will search for that file in the current directory.
Hint: There exists an constructor overload which takes an URL as argument.

How to get list of files from URL

I have an URL http ://......../somefolder/ I want to get the names of all the files inside this folder. I have tried this below code but it's showing error.
URL url = new URL("http://.............../pages/");
File f=new File(url.getFile());
String list[]=f.list();
for(String x:list)
{
System.out.println(x);
}
Error :-Exception in thread "main" java.lang.NullPointerException
at Directory.main(Directory.java:25)
It's not possible to do it like this.
HTTP has no concept of a "folder". The thing you see when you open that URL is just another web page, which happens to have a bunch of links to other pages. It's not special in any way as far as HTTP is concerned (and therefore HTTP clients, like the one built into Java).
That's not to say it's completely impossible. You might be able to get the file list another way.
Edit: The reason your code doesn't work is that it does something completely nonsensical. url.getFile() will return something like "/......./pages/", and then you pass that into the File constructor - which gives you a File representing the path /....../pages/ (or C:\......\pages\ on Windows). f.list() sees that that path doesn't exist on your computer, and returns null. There is no way to get a File that points to a URL, just like there's no way to get an int with the value 5.11.

What is the correct path for Toolkit.getImage()?

I need to upload an image file and generate a thumbnail for the uploaded file in my JSF webapplication. The original image is stored on the server in /home/myname/tomcat/webapps/uploads, while the thumbnail is stored in /home/myname/tomcat/webapps/uploads/thumbs. I'm using the thumbnail generator class I copied from philreeve.com.
I have successfully uploaded the file with help from BalusC. But using Toolkit.getImage(), I can't access the image.
I used the uploaded file's absolute path, like so:
inFilename = file.getAbsolutePath();
The relevant code from the thumbnail generator is:
public static String createThumbnail(String inFilename, String outFilename, int largestDimension) {
...
Image inImage = Toolkit.getDefaultToolkit().getImage(inFilename);
if (inImage.getWidth(null) == -1 || inImage.getHeight(null) == -1) {
return "Error loading file: \"" + new File(inFilename).getAbsolutePath() + "\"";
}
...
}
Since I am already using the absolute path, I don't understand why it is not working. I have also used the following values for inFilename, but I always get the "Error loading file...".
/home/myname/tomcat/webapps/uploads/filename.ext
/uploads/filename.ext
But I did check the directory, and the image is there. (I uploaded using /home/myname/tomcat/webapps/uploads/filename.ext, and it works.) What is the correct path for the image in that directory? Thank you.
Update
I got the code to work by using:
Image inImage = ImageIO.read(new File(inFilename));
I still don't understand why Toolkit.getImage() does not work though.
Are you sure it's a JPEG file? Use an image viewer to make sure nothing bad happened to the file during upload (or that it was an image to begin with).
Also, use new File(inFilename).exists() to make sure the path is correct. I also suggest to print new File(inFilename).getAbsolutePath() in error messages because relative paths can hurt you.
That said, the rest of the code looks correct.
The problem is that Toolkit.getImage() does not return the image immediately. The issue is well-described in this bug report, a relevant extract of which is here:
This is not a bug. The submitter is not properly using the asynchronous
Image API correctly. He assumes that getImage loads all of the image's bits
into memory. However, it is well documented that the actual loading of
bits does not take place until a call to Component.prepareImage or
Graphics.drawImage. In addition, these two functions return before the
Image is fully loaded. Developers are required to install an ImageObserver
to listen for notification that the Image has been fully loaded. Once they
receive this notification, they can repaint the Image.
I found that the answer to this question works well:
Image image = new ImageIcon(this.getClass().getResource("/images/bell-icon16.png")).getImage();

Java URL problem

A webpage contains a link to an executable (i.e. If we click on the link, the browser will download the file on your local machine).
Is there any way to achieve the same functionality with Java?
Thank you
Yes there is.
Here a simple example:
You can have a JSF(Java Server Faces) page, with a supporting backing bean that contains a method annotated with #PostConstruct This means that any action(for example downloading), will occur when the page is created.
There is already a question very similar already, have a look at: Invoke JSF managed bean action on page load
You can use Java's, URL class to download a file, but it requires a little work. You will need to do the following:
Create the URL object point at the file
Call openStream() to get an InputStream
Open the file you want to write to (a FileOutputStream)
Read from the InputStream and write to the file, until there is no more data left to read
Close the input and output streams
It doesn't really matter what type of file you are downloading (the fact that it's an executable file is irrelevant) since the process is the same for any type of file.
Update: It sounds like what you actually want is to plug the URL of a webpage into the Java app, and have the Java app find the link in the page and then download that link. If that is the case, the wording of your question is very unclear, but here are the basic steps I would use:
First, use steps 1 and 2 above to get an InputStream for the page
Use something like TagSoup or jsoup to parse the HTML
Find the <a> element that you want and extract its href attribute to get the URL of the file you need to download (if it's a relative URL instead of absolute, you will need to resolve that URL against the URL of the original page)
Use the steps above to download that URL
Here's a slight shortcut, based on jsoup (which I've never used before, I'm just writing this from snippets stolen from their webpage). I've left out a lot of error checking, but hey, I usually charge for this:
Document doc = Jsoup.connect(pageUrl).get();
Element aElement = doc.getElementsByTag("a").first() // Obviously you may need to refine this
String newUrl = aElement.attr("abs:href"); // This is a piece of jsoup magic that ensures that the destination URL is absolute
// assert newUrl != null
URL fileUrl = new URL(newUrl);
String destPath = fileUrl.getPath();
int lastSlash = destPath.lastIndexOf('/');
if (lastSlash != -1) {
destPath = destPath.substring(lastSlash);
}
// Assert that this is really a valid filename
// Now just download fileUrl and save it to destPath
The proper way to determine what the destination filename should be (unless you hardcode it) is actually to look for the Content-Disposition header, and look for the bit after filename=. In that case, you can't use openStream() on the URL, you will need to use openConnection() instead, to get a URLConnection. Then you can use getInputStream() to get your InputStream and getRequestProperty("Content-Disposition") to get the header to figure out your filename. In case that header is missing or malformed, you should then fall-back to using the method above to determine the destination filename.
You can do this using apache commons IO FileUtils
http://commons.apache.org/io/apidocs/org/apache/commons/io/FileUtils.html#copyURLToFile(java.net.URL, java.io.File)
Edit:
I was able to successfully download a zip file from source forge site (it is not empty), It did some thing like this
import java.io.File;
import java.net.URL;
import org.apache.commons.io.FileUtils;
public class Test
{
public static void main(String args[])
{
try {
URL url = new URL("http://sourceforge.net/projects/gallery/files/gallery3/3.0.2/gallery-3.0.2.zip/download");
FileUtils.copyURLToFile(url, new File("test.zip"));
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
I was able successfully download tomcat.exe too
URL url = new URL("http://archive.apache.org/dist/tomcat/tomcat-6/v6.0.16/bin/apache-tomcat-6.0.16.exe");

Categories