How to create a java.io.File Object with URI? - java

Users can upload images on my website. My servlet needs to write the uploads into directory images of my webapp. For writing it onto the disk I need to create a File() object.
One way is that I can hardcode the complete path to something like
new File("/usr/tomcat/webapps/ROOT/images/file.jpg")
Is there a way so that I can specify something like new File("images/file.jpg").. Can I do it using new File (URI uri ) so that I do not have to hardcode the complete path. My servlet is located inside /usr/tomcat/webapps/ROOT/WEB-INF/classes/
The images folder is not a directory. It is actually a symbolic link which is pointing to another directory on the filesystem outside tomcat

Don't store images under your webapp deployment directory: next time you'll redeploy the app, you will lose all your images. And moreover, there is not always a directory for a webapp, since it's typically deployed as a war file.
Store your images in an external location, at an absolute path, and configure Tomcat or another web server to serve images from this location, or implement a servlet which serves images from this location.
See Image Upload and Display in JSP for additional pointers.
EDIT:
If your problem is the hard-coded absolute path in the Java code, use a System property that you set when starting Tomcat, or a context param in the web.xml, or use a properties file to store the path, or your database.

You can get the web app path from the ServletContext object. You get the ServletContext from the HttpServletRequest object (http://docs.oracle.com/javaee/6/api/javax/servlet/ServletRequest.html#getServletContext%28%29).
See http://docs.oracle.com/javaee/6/api/javax/servlet/ServletContext.html#getRealPath%28java.lang.String%29
Concatenate the "real path" to the desired image file path and provide this as the parameter to the File constructor.

try{
String directory = //Store it in your Property file and pick it
String filename= //Generate Dynamic name or any specific format
// Create file
FileWriter fstream = new FileWriter(directory+filename);
BufferedWriter out = new BufferedWriter(fstream);
out.write("your content"); }
catch (Exception e){
System.err.println("Error: " + e.getMessage()); }
finally {
//Close the output stream
out.close();
}
You Can keep the directory path in you property file if it is not changing frequently.
Directory name can be absolute path which may be a hardrive path or you can save it in your webapp also but it always advisable any input file keep it outside the webapp.
File naming is always up to you if you want to keep the same file name then need to handle duplicate check other wise specify some dynamic format and named it.

Related

Instancing a java.io.File to read a resource from classpath

Supposing that I've a project structure as follows:
+ src
---+ main
------+ java
------+ resources
How can I define a java.io.File instance that is able to read an xml from resources folder?
It depends on what your program's working directory is.
You can get your working directory at runtime via System.getProperty("user.dir");
Here's a link with more info
Once you've got that, create a relative filepath pointing to your resource folder.
For example, if your working directory is src, create a relative filepath like so:
new File(Paths.get("main","resources").toString());
There are weaknesses with this approach as the actual filepath you use may change when you deploy your application, but it should get you through some simple development.
No, use an InputStream, with the path starting under resources.
InputStream in = getClass().getResourceAsStrem("/.../...");
Or an URL
URL url = getClass().getResource("/.../...");
This way, if the application is packed in a jar (case sensitive names!) it works too. The URL in that case is:
"jar:file://... .jar!/.../..."
If you need the resource as file, for instance to write to, you will need to copy the resource as initial template to some directory outside the application, like System.getProperty("user.home").
Path temp = Files.createTempFile("pref", "suffix.dat");
Files.copy(getClass().getResourceAsStream(...), temp, StandardCopyOption.REPLACE_EXISTING);
File file = temp.toFile();
As #mjaggard commented, createTempFile creates an empty file,
so Files.copy will normally fail unless with option REPLACE_EXISTING.

Get absolute path of a property file

My Java EE application includes many sub-projects, which should use a single one configuration file to connect to the database. I intend to write a Java class and make it an independent jar to read the database connection parameters from datasource.xml, which will be put on the path of the independent jar.
The questions I want to ask:
How to dynamic get the absolute path of the datasource.xml?
Can the solution of the first question work in all operating systems like UNIX, etc?
The first subject you have to deal with is where you store that file.
According to your question, you are going to be storing the file somewhere on the file system, externally to the actual application package. Therefore, you absolutely must know where the file is really located on the file system in order to access it; you can't conclude it in advance, unless you use environment variables that will instruct your code where the file is located.
A better approach is to package your XML file with the JAR. Then, you need not worry about absolute paths anymore. Simply use Thread.currentThread().getContextClassLoader().getResource(), providing the package-style path to the resource and you'll get a reference to it wherever it may be found.
If you can't package your file along with the JAR, you might be able to store it in a directory on the file system and add that directory to your server's classpath lookup sequence; some application servers support that. Then, you can still use the classloader to look up the resource, without requiring to know its absolute location.
What about this? Converting a relative path to absolute during runtime.. I guess that should work on all enviroments...
File a = new File("/some/abs/path");
File parentFolder = new File(a.getParent());
File b = new File(parentFolder, "../some/relative/path");
String absolute = b.getCanonicalPath(); // may throw IOException
regards
You can make use of Environment Variables
String path = System.getEnv("MYVARIABLE");
File datasource = path + "/datasource.xml";
Or read in the location from a properties file available in a constant location
Properties props = new Properties();
try {
props.load("MyFixed.properties");
} catch(Exception e) {
e.printStackTrace(); // Can do better
}
String path = props.getProperty("datasource.path");
File datasource = path + "/datasource.xml";
Or pass in a VM argument when starting the Jar with -D
String path = System.getProperty("datasource.path");
File datasource = path + "/datasource.xml";
and call with
java -jar -Ddatasource.path=/my/path/to/datasource.xml my.jar

use a URL object to read a resource in web content

Im working in a web application using JSF2 and in one of my forms I create a PDF file that contains a image and a specific font. The ressorces are located in the WebContent directory.
My problem is when I want to create the pdf File I want to read the ressources and pass it in parameters to the method creating PDF FILE. I dont know how to use the URL object or any other way to do the task.
Thanks.
The ressorces are located in the WebContent directory.
WebContent directory is just for development environment under eclipse. When deployed the files there would go into the root of the web-app. So I take it that you want to access files in the root of your web-app.
You can use ServletContext.getResource(String path) with a path as "/myFileName" where the / signifies the web-app context root.
To get the reference to the ServletContext you may try this
The URL class has an openStream() method which gives you an InputStream of the resource's content:
URL resource = externalContext.getResource("/image.png");
InputStream input = resource.openStream();
// ...
You can also immediately get the resource as stream without getting it as URL first:
InputStream input = externalContext.getResourceAsStream("/image.png");
// ...
Having the InputStream, you can just read it into whatever target object which your PDF creator is expecting as input.

Upload file to directory on server using Java and JSP - can't get path right

On my vps, I want to upload a file to the Logos directory.
The directory structure is as follows on my vps -
/home/webadmin/domain.com/html/Logos
When a file is uploaded through my jsp page, that file is renamed, and then I want to put it into the Logos directory.... but I can't seem to get the path right in my servlet code.
Snippet of servlet code -
String upload_directory="/Logos/"; // path to the upload folder
File savedFile = new File(upload_directory,BusinessName+"_Logo."+fileExtension);
//.....
//file saved to directory
//.....
I've tried many variations, but still fail. What is the proper way to specify the path?
Edited
The problem with using getServletContext() is that it returns the path to the directory where Tomcat and my webapp is...whereas I want to reach the directory where my html and image files are - under the root directory of the vps. How do I specify that path?
String server_path = getServletContext().getRealPath("/"); // get server path.
//server_path = /opt/tomcat6/webapps/domain.com/
String upload_directory = "Logos/"; // get path to the upload folder.
String complete_path = server_path + upload_directory; // get the complete path to the upload folder.
//complete_path = /opt/tomcat6/webapps/domain.com/Logos/
File savedFile = new File(complete_path,"NewLogo.jpg");
//savedFile = /opt/tomcat6/webapps/domain.com/Logos/NewLogo.jpg
It's a common practice to make the path for storage configurable - either via some application.properties file, or if you don't have such a properties file - as a context-param in web.xml. There you configure the path to be the absolute path, like:
configuredUploadDir=/home/webadmin/domain.com/html/Logos
Obtain that value in your code (depending on how you stored it), and have:
File uploadDir = new File(configuredUploadDir);
Note: make sure you have the permissions to read and write the target directory.
You can use following code in any jsp or servlet.
1) String serverPath= getServletContext().getRealPath("/");
This will give you full path of the server from root directory to your web application directory.
For me its: "D:\local\tomcat-6.0.29\webapps\myapp" when I sysout from myapp application.
Once you got the whole real path for the server system as above you can get the path relative to your directory. So if I have some data file in myapp\data - I can get it appending \data\filename to the serverPath which we got earlier.
This will work in all situation even you have multiple servers installed on the same system.
2) You can get server home from system properties using
System.getProperty("TOMCAT_HOME")
and then can use this absolute path in your program
3) To pass absolute directory path to any servlet using <init-param>
Hope this will work for you.
Well, the problem is: the File constructor doesn't create the file, only prepares to for the creation, then, after you construct a file instance you must invoke the method createNewFile(), and thats all.
The path "/Logos/" will attempt to create the file in the root of your system, which is not what you want. Look at the ServletContext.getRealPath() method.

Getting the absolute path of a file within a JAR within an EAR?

I have a J2EE app deployed as an EAR file, which in turn contains a JAR file for the business layer code (including some EJBs) and a WAR file for the web layer code. The EAR file is deployed to JBoss 3.2.5, which unpacks the EAR and WAR files, but not the JAR file (this is not the problem, it's just FYI).
One of the files within the JAR file is an MS Word template whose absolute path needs to be passed to some native MS Word code (using Jacob, FWIW).
The problem is that if I try to obtain the File like this (from within some code in the JAR file):
URL url = getClass().getResource("myTemplate.dot");
File file = new File(url.toURI()); // <= fails!
String absolutePath = file.getAbsolutePath();
// Pass the absolutePath to MS Word to be opened as a document
... then the java.io.File constructor throws the IllegalArgumentException "URI is not hierarchical". The URL and URI both have the same toString() output, namely:
jar:file:/G:/jboss/myapp/jboss/server/default/tmp/deploy/tmp29269myapp.ear-contents/myapp.jar!/my/package/myTemplate.dot
This much of the path is valid on the file system, but the rest is not (being internal to the JAR file):
G:/jboss/myapp/jboss/server/default/tmp/deploy/tmp29269myapp.ear-contents
What's the easiest way of getting the absolute path to this file?
My current solution is to copy the file to the server's temporary directory, then use the absolute path of the copy:
File tempDir = new File(System.getProperty("java.io.tmpdir"));
File temporaryFile = new File(tempDir, "templateCopy.dot");
InputStream templateStream = getClass().getResourceAsStream("myTemplate.dot");
IOUtils.copy(templateStream, new FileOutputStream(temporaryFile));
String absolutePath = temporaryFile.getAbsolutePath();
I'd prefer a solution that doesn't involve copying the file.
Unless the code or application you are passing the URI String to accepts a format that specifies a location within a jar/zip file, your solution of copying the file to a temporary location is probably the best one.
If these files are referenced often, you may want to cache the locations of the extract files and just verify their existance each time they are needed.
You should copy the contents to a temporary file (potentially with a cache), because trying to get to internal files of the application container is a dependency you want to avoid. There may not even be an extracted file at all (it can load from the JAR directly).

Categories

Resources