This question already has answers here:
How to find the working folder of a servlet based application in order to load resources
(3 answers)
Closed 6 years ago.
I currently have a bunch of images in my .war file like this.
WAR-ROOT
-WEB-INF
-IMAGES
-image1.jpg
-image2.jpg
-index.html
When I generate html via my servlets/jsp/etc I can simple link to
http://host/contextroot/IMAGES/image1.jpg
and
http://host/contextroot/IMAGES/image1.jpg
Not I am writing a servlet that needs to get a filesystem reference to these images (to render out a composite .pdf file in this case). Does anybody have a suggestion for how to get a filesystem reference to files placed in the war similar to how this is?
Is it perhaps a url I grab on servlet initialization? I could obviously have a properties file that explicitly points to the installed directory but I would like to avoid additional configs.
If you can guarantee that the WAR is expanded, then you can use ServletContext#getRealPath() to convert a relative web path to an absolute disk file system which you can further use in the usual Java IO stuff.
String relativeWebPath = "/IMAGES/image1.jpg";
String absoluteDiskPath = getServletContext().getRealPath(relativeWebPath);
File file = new File(absoluteDiskPath);
InputStream input = new FileInputStream(file);
// ...
However, if you can't guarantee that the WAR is expanded (i.e. all resources are still packaged inside WAR) and you're actually not interested on the absolute disk file system path and all you actually need is just an InputStream out of it, then use getServletContext().getResourceAsStream() instead.
String relativeWebPath = "/IMAGES/image1.jpg";
InputStream input = getServletContext().getResourceAsStream(relativeWebPath);
// ...
See also:
getResourceAsStream() vs FileInputStream
Use the getRealPath method of ServletContext.
Ex:
String path = getServletContext().getRealPath("WEB-INF/static/img/myfile.jpeg");
This is relatively straight forward you simply use the class loader to fetch the files from the class plath. :
InputStream is = YourServlet.class.getClassLoader().getResourceAsStream("IMAGES/img1.jpg");
There are a few other getResoruce classes that are worth looking at. Also you don't have to fetch the class loader through the class variable on your servlet. Any class that you happen to know has been loaded by the container should work .
If you know the relative location of the files you could ask the runtime about the exact location using
Thread.currentThread().getContextClassLoader().getResource(<relative-path>/<filename>)
This would give you an URL to the location where the specified image can be found. This URL can be used to read the specified file or you can split it to use the different parts of the URL for further processing.
Related
I have a little problem with Struts 2 when I try to get the context path :
ServletActionContext.getServletContext().getRealPath("\\WebContent\\resources\\img\\");
I got this path:
C:\Users\killian\workspace.metadata.plugins\org.eclipse.wst.server.core\tmp0\wtpwebapps\SiteWebAdministrable\WebContent\resources\imgicone.jpg
Why the exact source path ?
Because i need to upload and save images for an admin website to control background and without the actual path i cannot save images in the resources path...
So i save the path with the name and extension in the database (no problem), and i need to save the image in the resource directory (image problem...)
Can someone help me please ? Did i forgot something ?
This question is the answer ?
How do you get the project path in Struts 2?
servletContext.getServletContext().getRealPath("/resources/img/name_of_image.png")
So, passing the "/" to getRealPath() would return you the absolute disk file system path of the /web folder of the expanded WAR file of the project. Something like /path/to/server/work/folder/demo.war/ which you should be able to further use in File or FileInputStream.
Note that most starters don't seem to see/realize that you can actually pass the whole web content path to it and that they often use
String absolutePathToIndexJSP = servletContext.getRealPath("/") + "demo.png";
instead of
String absolutePathToIndexJSP = servletContext.getRealPath("/demo.png");
getRealPath() is unportable; you'd better never use it
Use getRealPath() carefully.
If all you actually need is to get an InputStream of the web resource, better use ServletContext#getResourceAsStream() instead, this will work regardless of the way how the WAR is expanded. So, if you for example want an InputStream of index.jsp, then do not do:
InputStream input = new FileInputStream(servletContext.getRealPath("/demo.png")); // Wrong!
But instead do:
InputStream input = servletContext.getResourceAsStream("/demo.png"); // Right!
Or if you intend to obtain a list of all available web resource paths, use ServletContext#getResourcePaths() instead.
Set<String> resourcePaths = servletContext.getResourcePaths("/");
I'm having trouble coverting from a URI to a nio.Path in the general case. Given a URI with multiple schemas, I wish to create a single nio.Path instance to reflect this URI.
//setup
String jarEmbeddedFilePathString = "jar:file:/C:/Program%20Files%20(x86)/OurSoftware/OurJar_x86_1.0.68.220.jar!/com/our_company/javaFXViewCode.fxml";
URI uri = URI.create(jarEmbeddedFilePathString);
//act
Path nioPath = Paths.get(uri);
//assert --any of these are acceptable
assertThat(nioPath).isEqualTo("C:/Program Files (x86)/OurSoftware/OurJar_x86_1.0.68.220.jar/com/our_company/javaFXViewCode.fxml");
//--or assertThat(nioPath).isEqualTo("/com/our_company/javaFXViewCode.fxml");
//--or assertThat(nioPath).isEqualTo("OurJar_x86_1.0.68.220.jar!/com/our_company/javaFXViewCode.fxml")
//or pretty well any other interpretation of jar'd-uri-to-path any reasonable person would have.
This code currently throws FileSystemNotFoundException on the Paths.get() call.
The actual reason for this conversion is to ask the resulting path about things regarding its package location and file name --so in other words, as long as the resulting path object preserves the ...com/our_company/javaFXViewCode.fxml portion, then its still very convenient for us to use the NIO Path object.
Most of this information is actually used for debugging, so it would not be impossible for me to retrofit our code to avoid use of Paths in this particular instance and instead use URI's or simply strings, but that would involve a bunch of retooling for methods already conveniently provided by the nio.Path object.
I've started digging into the file system provider API and have been confronted with more complexity than I wish to deal with for such a small thing. Is there a simple way to convert from a class-loader provided URI to a path object corresponding to OS-understandable traversal in the case of the URI pointing to a non-jar file, and not-OS-understandable-but-still-useful traversal in the case where the path would point to a resource inside a jar (or for that matter a zip or tarball)?
Thanks for any help
A Java Path belongs to a FileSystem. A file system is implemented by a FileSystemProvider.
Java comes with two file system providers: One for the operating system (e.g. WindowsFileSystemProvider), and one for zip files (ZipFileSystemProvider). These are internal and should not be accessed directly.
To get a Path to a file inside a Jar file, you need to get (create) a FileSystem for the content of the Jar file. You can then get a Path to a file in that file system.
First, you'll need to parse the Jar URL, which is best done using the JarURLConnection:
URL jarEntryURL = new URL("jar:file:/C:/Program%20Files%20(x86)/OurSoftware/OurJar_x86_1.0.68.220.jar!/com/our_company/javaFXViewCode.fxml");
JarURLConnection jarEntryConn = (JarURLConnection) jarEntryURL.openConnection();
URL jarFileURL = jarEntryConn.getJarFileURL(); // file:/C:/Program%20Files%20(x86)/OurSoftware/OurJar_x86_1.0.68.220.jar
String entryName = jarEntryConn.getEntryName(); // com/our_company/javaFXViewCode.fxml
Once you have those, you can create a FileSystem and get a Path to the jar'd file. Remember that FileSystem is an open resource and needs to be closed when you are done with it:
try (FileSystem jarFileSystem = FileSystems.newFileSystem(jarPath, null)) {
Path entryPath = jarFileSystem.getPath(entryName);
System.out.println("entryPath: " + entryPath); // com/our_company/javaFXViewCode.fxml
System.out.println("parent: " + entryPath.getParent()); // com/our_company
}
I am writing webApp that use jsp file to call java class directly to get results.
The JSP file is like:
<%
String queryKey = request.getParameter("id");
int jobID = Integer.parseInt(queryKey);
out.println(jobID);
ArrayList<Integer> myTopList = JobRecByBoWJaccard.topJobsByBoW(jobID);
%>
In java classes the files are accessed through:
BufferedReader br = new BufferedReader(new FileReader("WebContent/StopWords/stop-words-english1.txt"));
and
private InputStream modelInputT = new FileInputStream("WebContent/OpenNLP_Models/en-token.bin");
The tomcat cannot find the referenced files and someone said use getResourceAsStream, but that is for servlets. I call the java class directly without any servlets.
private InputStream modelInputT = = this.getClass().getClassLoader().getResourceAsStream("WebContent/OpenNLP_Models/en-token.bin");
This cause java class cannot find the file as well. Need help and how to make changes to these java classes?
The tomcat cannot find the referenced files ...
That is because the pathnames are incorrect unless the JVM's current directory is the parent directory of the "WebContent" directory. When you use FileInputStream to open a file, relative pathname are resolved relative to the current directory of the JVM when it was launched.
... and someone said use getResourceAsStream, but that is for servlets.
No. That's not correct either. That method is not "for servlets". The purpose of that method is to open a resource that is on the class / classloader's classpath. If your "WebContent/StopWords/stop-words-english1.txt" is in the webapp's "/WEB-INFO/classes" or in a JAR file in "/WEB-INFO/lib", then getResourceAsStream will find it.
In your case, it seems like you are talking about the "WebContent" directory that corresponds to the default servlet.
In that case, read this Q&A - How can I get real path for file in my WebContent folder?.
So if you are trying to access those files from within a JSP, it seems as if you should be writing this:
new FileReader("WebContent/StopWords/stop-words-english1.txt")
as this:
new FileReader(getServletContext().getRealPath(
"/StopWords/stop-words-english1.txt"))
I've seen some posts on using java.lang.Class.getResources() and java.lang.Class.getResourcesAsStream() on SO today. Somehow, I still have confusion.
I have a Jar file that contains this structure (resources/test.xml)
This jar file is on the classpath of my application, and when I call below piece of code, it returns null, i.e. value of mappingURL is null.
URL mappingURL = this.getClass().getResource("/resources/test.xml");
However when I store the XML file in exploded format on the classpath i.e. by creating a directory "resources" and storing mapping.xml inside, it works.
I'm using this URL for reading the content of the "test.xml" file later.
Does that mean, getResources() is not the appropriate method for reading the files from inside a Jar? I didn't understand why mappingURL is null when file (test.xml) is present in the Jar file?
The getResource() method will return null if it cannot find the resource. You are prefixing the resource with a / which means that it is trying to look in the folder. You should be able to remove the leading / and achieve your intended result.
Here is the getResource() method description from the documentation:
Finds the resource with the given name. A resource is some data (images, audio, text, etc) that can be accessed by class code in a way that is independent of the location of the code.
The name of a resource is a '/'-separated path name that identifies the resource.
This method will first search the parent class loader for the resource; if the parent is null the path of the class loader built-in to the virtual machine is searched. That failing, this method will invoke findResource(String) to find the resource.
this.getClass().getResource("/resources/test.xml");
That should work, provided that the class file you are starting with is also in the same JAR file.
Does that mean, getResources() is not the appropriate method for
reading the files from inside a Jar?
This is correct. If your resource will be bundled in a jar, you always want to use getResourceAsStream().
A single line later and you can start reading the file:
BufferedReader reader = new BufferReader(InputStreamReader(getResourceAsStream("/test.xml")));
reader.readLine();
//...
I'm trying to upload an external image and I need to save it in a folder where I have a managed bean. Any idea how I could do this?
Use Class#getResource() to obtain the URL where the class is located.
URL beanClassPath = Bean.class.getResource("");
File imageFile = new File(beanClassPath.getPath(), imageFileName);
// ...
However, this is generally a very bad idea. If you redeploy the webapp, everything will get lost. Rather store the images in a fixed path somewhere outside the webapplication, e.g. /images or so. In a Windows environment this will automatically refer to the disk from where the webapplication is started, e.g. c:/images.
File imageFile = new File("/images", imageFileName);
// ...
You can also consider to store them in a database, you'll only need to store some metadata along it, such as the original filename, content type and preferably also the content length and eventually the creation and last modification timestamps. That kind of information which you would usually obtain using the java.io.File methods. You'll namely going to need them whenever you'd like to serve the image back to the webpage.