This is driving me bonkers. I'm writing a web app in Java and all I want to do is verify the existence of an image that's saved to an /images folder right under the web root.
The 1,000,000 google searches I did seemed to indicate that the File.exists(path) method is the way to go. But for obvious reasons, I don't want to hard code the path.
Physically, the test image file I'm working with exists on my D-drive at, let's say, D:\documents\images\myimage.jpg. GlassFish is my local server and I don't think my image files are replicated to a "GlassFish folder" when my app is deployed, so I think the only physical copy is the one on the D: drive.
The only way I can get:
boolean fileExists = new File(somePath).exists();
to return TRUE is using the string "D:\documents\images\myimage.jpg". What I was after is a test like exists() that maybe uses a URL that I could couple with some other method or parameter that references the site root and I could build the rest of the URL relative to that.
Any help is much appreciated.
Since documents is the web root, you should be able to use the ServletContext.getRealPath(String) method.
ServletContext context = servletRequest.getSession().getServletContext();
// Or if you have the servlet instead of request, use this:
// ServletContext = servlet.getServletContext(); // see comment by BalusC
String virtualPath = "/images/myimage.jpg";
String realPath = context.getRealPath(virtualPath);
// realPath will be D:\documents\images\myimage.jpg
http://download.oracle.com/javaee/5/api/javax/servlet/ServletContext.html#getRealPath(java.lang.String)
Returns a String containing the real path for a given virtual path. For
example, the path "/index.html" returns the absolute file path on the server's
filesystem would be served by a request for "http://host/contextPath/index.html",
where contextPath is the context path of this ServletContext..
The real path returned will be in a form appropriate to the computer and
operating system on which the servlet container is running, including the proper
path separators. This method returns null if the servlet container cannot translate
the virtual path to a real path for any reason (such as when the content is being
made available from a .war archive).
Maybe you can put your images in the war file and use getResourceAsStream to get the file?
In that case the path would be relative to the root of the war file
Related
I'm trying to create a file in my server. I have sent a image, and I want to create that Image in a folder of my server, but with relative path.
String filePath = "C:\\Users\\Administrador\\Desktop\\Proyecto\\clienteServidor\\Server\\folder\\image.jpg";
File imageFile = new File(filePath);
...
I'm doing with the absolute path.
Thanks
hard coding a directory is seldom good for coding. What happens if there is a typo in your code. Using a combination of ./ or ./*
or even using
new File(MyClass.class.getProtectionDomain().getCodeSource().getLocation().getPath());
This is explained here.
It is doable but, as Dmitry said, it might not work on every server. SecurityManager class should be consulted if your webapp has the privilege to write to that folder. or you will get an exception.
One way to do it is via ServletContext:
URL webAppRoot = this.getServletConfig().getServletContext()
.getResource("/images/new-image.jpg");
This will point to your ${tomcat}/webapps/mywebapp/images/new-image.jpg.
Another way is via ProtectionDomain:
URL runningClassLocation = this.getClass().getProtectionDomain()
.getCodeSource().getLocation();
But this will most likely give you jar:file://...myapp.jar!/my/package/servlet.class.
After you have the URL you convert it to File and append any relative path to your image folder.
UPDATE:
I agree with Jim, and emphasize that doing it like this is just for academic purposes.
Java is not like PHP so you shouldn't have uploads folder inside your web application's folder. Usually this is done by enabling an administrator-level user to specify a file path to a folder reserved for your application's storage needs.
I have a web application running under tomcat 7, and in one of the class, Im trying to read a file in one of the jar under WEB-INF/lib folder.
URL resourceURL = MyClass.class.getClassLoader().getResource("xml/xslt/master.xsl");
File xslfile = new File(resourceURL.getPath());
AssertUtil.assertTrue(xslfile.exists(),"xsl file not found");
Both MyClass and master.xsl resides in the same jar and there is no issue with packaging. But above snippet fails in the assertion statement as xslfile.exists returns false. The URL correctly resolves to the location of the file inside the jar as given below
file:/<MY_WEBAPP_LOCATION>/MyApp/WEB-INF/lib/MyComponent.jar!/xml/xslt/master.xsl
where MY_WEBAPP_LOCATION corresponds to the absolute path to my tomcat servers webapp directory.
But if I rewrite the code as below to read as inputstream, it works fine.
InputStream xslFile = MyClass.class.getClassLoader().getResourceAsStream("xml/xslt/master.xsl");
Can anyone explain what is preventing the creation of File from the jar resource, whereas the inputstream creation is working perfectly fine. Is there any additional permission settings needed from tomcat side, to read a file inside jar ?
EDIT: One more observation, if the file is placed under WEB-INF/classes, creation of File with above code works fine. Issue is only when it is placed in a jar under WEB-INF/lib
Be careful it seems that ClassLoader.getResource does not handle relative path.
See this.
GetResourceAsStream happens to take the path relative to the ClassLoader (and not the class !!). I think you're lucky enough that there are the same here.
If it is a Desktop application getResource() will work
But as this is a web application the resource needs to be extracted from Context , hence getResoruceAsStream()
It is not a permission problem, but the use of java.io.File API - in particular constructor http://docs.oracle.com/javase/7/docs/api/java/io/File.html#File%28java.lang.String%29
When you are constructing File object using
File xslfile = new File(resourceURL.getPath());
you are using java.io.File#File(String) method which expects an "abstract pathname". What is an acceptable/valid pathname is described by javadoc of the File class: http://docs.oracle.com/javase/7/docs/api/java/io/File.html
String value that your are getting from getPath() method:
file:/<MY_WEBAPP_LOCATION>/MyApp/WEB-INF/lib/MyComponent.jar!/xml/xslt/master.xsl
simply does not constitute a valid "abstract pathname" - it is a URL that is converted to a java.lang.String (and IMHO should be returned with URL scheme of "jar" and not "file"). Therefore a call to
isExist()
returns false as there is no file with such name on your disk.
On the other hand if the resource is outside of a jar (e.g. under WEB-INF/classes directory) resourceURL.getPath() will return a value that presents a valid abstract pathname as the resource in question is indeed a simple file.
When you use java.lang.ClassLoader#getResourceAsStream(java.lang.String) the method streams out the resource directly into a java.lang.InputStream and might not even use File class in its implementation.
Synopsis
Given the following (abridged) code that lives server-side on a servlet (Tomcat is the container). This is a GWT application, though that should be irrelevant (I think).
ServletContext context = getServletContext();
String dataFilePath= context.getRealPath("/WEB-INF/dir/dataFile.txt");
File dataFile = new File(dataFilePath);
TestCaseGenerator testCaseGenerator = new TestCaseGenerator(dataFile);
testCaseGenerator.generateTestCase();
TestCaseGenerator is a class from a jar in the project's war/WEB-INF/lib folder, that's been added to the GWT project as an external library.
The Problem
When testCaseGenerator.generateTestCase() gets executed, it's unable to use dataFile to create a new LineNumberReader(new FileReader(dataFile));, a FileNotFoundException gets thrown.
I've verified that the String value of dataFilePath is correct and contains the proper real path to the file on the server I need to read from, as well that dataFile isn't null. I've also verified that TestCaseGenerator runs just fine when called from a command line, outside of this GWT application.
I'm not sure why TestCaseGenerator isn't able to use the File object I pass it, considering I'm passing it the real file path of the file. I can come up with some alternative solutions to get around this issue, but now I'm genuinely curious why it isn't able to find the file.
Thanks in advance for any insight.
Solved
I foolishly neglected to include the dir/dataFile.txt in my build.xml's war target, so in fact the file wasn't being included in the war package, and thus never placed within the Tomcat container.
<include name="dir/**" />
And I also misunderstood what context.getRealPath("/WEB-INF/dir/dataFile.txt"); actual returns;. From ServletContext javadoc
Gets the real path corresponding to the given virtual path. For
example, if path is equal to /index.html, this method will return the
absolute file path on the server's filesystem to which a request of
the form http://://index.html would be
mapped, where corresponds to the context path of this
ServletContext.
So even though getRealPath returns a path value, it doesn't necessarily mean the file is at that actual path.
I am working on web application.I invoke on my jsp request.getContextPath(), but strangely I got address /streetshop.
Then I am appending some path as request.getContextPath() + "abc" and create folder.
Then its creating folder in D:// instead of my webapplication folder.
Please, tell me, I want to upload an image in put it in my web-application root/images/images.gif.
You mix things up here. HttpServletRequest.getContextPath() returns your web application root path. In your example this is /streetshop, so your URL may look similar to www.myapp.com/streetshop. If you want to access the internal file system path, you must obtain it from the ServletContext using request.getServletContext().getRealPath("/"). This should return the location of your WAR files' WebContent folder.
Keep in mind that if you modify contents of this path during runtime, you're going to loose everything when redeploying your application.
I'm developing a web application in java to control my stock and do some other things. I upload files through a JSF component. This files are images. Anyway, my question is, I want these images to be stored in the web application's resource folder. More specifically in a subfolder named "userUploads". I create a File object but how do I a get a String representing that path?
If you want your files to be stored in your "web application's resource folder" I'm guessing you mean a folder called 'resources' inside the 'webroot'. While this is not really the best approach, you can achieve this by using the ServletContext:
ServletContext sc = httpRequest.getSession().getServletContext();
String path = sc.getPath("resources");
or
File file = new File(sc.getPath("resources"))
Personally, I'd recommend creating your 'uploads' folder outside of your web app's directory, so that it is not replaced during deployment etc.
"I create a File object but how do I a get a String representing that path?"
If you have a File object, you can call myFile.getAbsolutePath() to get a string representation of the path.
Do the following:
Get the HttpSession from the HttpServletRequest.
Get the ServletContext from the HttpSession.
Get the absolute path to your installation using the ServletContext.getRealPath() method. The parameter to this method is a path that is relative to your context root.
Here is a link: ServletContext