I want to download a file from one of the EBS volumes I created on Amazon Elastic block storage. Mostly it is advisable to used ServletContext#getResource() and its counterpart ServletContext#getResourceAsStream() as well advised here.
But in this case is the following code advisable
InputStream in = new FileInputStream(new File(FOLDER_PATH_ON_AMAZON_EBS + "/" + folder + "/" + fileName));
It's hard to tell what the question is here.
If you are asking whether it is better to use getServletContext() or new File(PATH_TO_EBS...) then it simply depends on what you are running. If you are running a standalone java application and requesting files via sockets, then you would use the latter (a FileInputStream over a file you know where to look). If you are running a web server (eg Tomcat) and will be using a web client to download the file, then you would typically use the getServletContext() since that is part of the web-server infrastructure.
Both ways let you get a handle on the file, but getServletContext() is going to refer to a location for your application under Tomcat's working area. Are you going to mount your EBS volume somewhere where you can easily reach it starting from Tomcat's working area.
If you are running a web server and it is allowing you to reach a file directly in your EBS volume with new FileInputStream(new File(MY_EBS_LOCATION + "/" + ...)) then use it by all means - clear and easy.
Having the file path in the properties file, and using the absolute path is better due the following reasons,
There are chances that the mountpoint of the ec2 volume changes, having that in the classpath and modifying that is comparatively harder than modifying the entry in the properties file.
Normally resources like property files are got using getResource(), if there is going to be other IO like storing photos, office docs then its wise to use absolute path for access.
It also depends on the usecase if the files(resource) is frequently used by the application, and the application only, then u can have that in classpath and pack it along with the archive.
Related
I've looked at a number of related cases here on stackoverflow related to this, but mostly deal with the situation of deciding where to put external files and access them, which is quite clear.
In my situation, I have a Java EE application that needs to use a third party library that reads an external config file to determine the location of another file. I am using Eclipse and Tomcat.
The external config file has a line that reads like: FILENAME=[path], where path is expected to be the full path name to the file.
I have no way of knowing how they access the file, save to say that specifying /WEB-INF/classes/file or just file does not work, the library can't find it. However when I put the full name /Users/.../file on my local machine, it can find it.
As this is intended to be deployed on production server in the cloud, is my only solution to put the needed file in cloud storage, then set the config file to point to this absolute location ?
I need to make a file in the Android External Storage area that can be accessed (read/write) by other apps.
I looked here but that says to pass it a directory type such as DIRECTORY_MUSIC, DIRECTORY_PICTURES etc.
But none of those types is what i want. So what I'm thinking is this:
File F = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "MyAppName" + File.separator + "MyFile");
Will this work or how can i ensure that a file will truly have public read/write access for other apps?
Also, I read somewhere that OutputStreams are only supposed to take a name with no path, and are always private, so how would i read/write ints to F?
Well, it seems to me that the statement for creating a new File you have there, would work. Although, why not try it out? Also, it is absolutely possible to write to a file and have it be accessible publicly, you do not need to do anything for this to happen, it will just happen by default. Reading/writing ints from/to the File can be done as usual, I recommend converting it to a String before writing.
It will works. You can ensure that a file truly have public access if you'll find it with some file manager and try to open it. In your example path to your file will be "%HOME_DIR%\MyAppName\MyFile". Also for creating file you could use FileOutputStream (not OutputStream), it takes File as parameter in constructor.
Files created in external storage are by default can be accessed by any other app (since the file is in external storage). The only thing you can control is the lifetime of the created file. As in whether the file should exist with your app only and deleted once the app is uninstalled or the file exists even after your app is removed.
If you want to create a file on your own path (not in DIRECTORY_PICTURE etc) inside your application then use getExternalFileDir() and pass null to it. See the link below for more details.
Saving file in external storage
I have a Java Servlet/JSP application which requires the user to upload an archive file (either .rar or .zip). This archive file is then extracted, and the extracted files are parsed. After parsing the files, the data in them is added to the database and the files are deleted again.
On my local machine, this works perfectly, since you just use the filesystem provided by the OS. But now I'd like to run this application on Heroku and I'm unsure on how to do the file uploads.
Since these files are user specific, and not permanent, my initial thoughts were that I could just use the ephemeral file system provided by Heroku and I do not require the use of S3.
At the moment, my application runs on only 1 web dyno and no worker dyno's but in the future this may get scaled to multiple web dyno's, depending on the amount of users that are going to use it.
Can I use the ephemeral file system for my specific use case, and will it scale properly?
I am currently writing using ServletFileUpload, and am writing to java.io.File; Can I just change the path of my java.io.File to a path in the ephemeral file system? What would be an example of such path?
I guess you can use the ephemeral fileystem in your specific case, as it's just a temporary usage for parsing the file.
You can use the /tmp directory but keep in mind that the file will be destroyed after the request is complete.
This is discussed in this post https://stackoverflow.com/a/12416923/476782
This question already has answers here:
How to save uploaded file in JSF
(2 answers)
Closed 7 years ago.
Here with another question on Images ( which seems to be more difficult than I initialy predicted) I'm working on a java Web app with JSF 2.0 ( apache myFaces) and I want this app to be able to upload a picture to a destination on the server it's going to run on. I have a Windows r2 2008 Server running a mySQL Db, but I don't want to store the image in the db, I'd rather store it somewhere in the server and then just save the path as a string in the db.
I was told this is the best way, but I can't seem to find an example on how to save it on the server. I run the app on the Apache tomcat Server as a WAR file. so I don't know if I have to save the file to a path on the server drive (i.e. C:\images) or a special folder in the project itself ( within the java, html files) any help at all is greatly appreciated. I'm totally lost and have been stuck the whole day trying to figure this out.
The code I use to upload the image to the java class is this ( courtesy of CodyS):
InputStream is = uploadedFile.getInputStream();
byte[] buffer = new byte[(int) uploadedFile.getSize()];
is.read(buffer);
File f = new File("C:\\temp\\" + this.patient.getPk() + ".jpeg");
f.createNewFile();
FileOutputStream fos = new FileOutputStream(f);
fos.write(buffer); //This is where I write it to the C Drive
fos.close();
is.close();
instead of writing it to my C drive I'm going to run it on the server, but where should I store the image to later retriev and display in an xhtml file? I hope I'm being clear on what I need, let me know if I am not and I'll try to explain in another way.
instead of writing it to my C drive I'm going to run it on the server, but where should I store the image to later retriev and display in an xhtml file?
That depends on how much control you have over configuring the server. Ideal would be to configure a fixed path outside the Tomcat webapps folder. For example, /var/webapp/upload. You can set this path as a VM argument or environment variable so that your webapp can retrieve it programmatically without the need to change the code.
For example, when specifying as VM argument -Dupload.location=/var/webapp/upload, you can complete the upload as follows:
Path folder = Paths.get(System.getProperty("upload.location"));
String filename = FilenameUtils.getBaseName(uploadedFile.getName());
String extension = FilenameUtils.getExtension(uploadedFile.getName());
Path file = Files.createTempFile(folder, filename + "-", "." + extension);
try (InputStream input = uploadedFile.getInputStream()) {
Files.copy(input, file, StandardCopyOption.REPLACE_EXISTING);
}
String uploadedFileName = file.getFileName().toString();
// Now store it in DB.
As to serving the file back, most ideal would be to add the upload location as a separate <Context> to Tomcat. E.g.
<Context docBase="/var/webapp/upload" path="/uploads" />
This way you can access it directly by http://example.com/uploads/foo-123456.ext
If you have zero control over configuring the server, then, well, storing in the DB or sending to a 3rd party host such as Amazon S3 is your best bet.
See also:
How to provide relative path in File class to upload any file?
Reliable data serving
I would consider allowing the user to upload to Amazon S3 directly. Amazon offers a service for that. Using that service, the client would post a form with the file directly to S3. Once the file has arrived there, Amazon will redirect the client to one of your endpoints, to confirm that the data has arrived, passing you the relevant details.
The benefits are:
Your server does not spend a lot of time in receiving huge files. You can spend your CPU cycles on something a little bit more interesting.
The availability guaranteed by storing it on S3 is probably better then what you would get by storing it on your own Windows box.
It scales. At some point, your filesystem will run out of space. (Or you reach the limit of what you can store inside a folder.)
I'd suggest that you save your images in a subfolder which is in your application's WEB-INF folder. Remember that when you use Tomcat, your WAR files will be extracted automatically. This approach also has the advantage that you can always migrate your application to another server, you only have to save the path relative to WEB-INF folder in your DB.
Consider the following example structure
- Project
- www
- files
+ documents
+ html
+ images
+ scripts
- WEB-INF
* web.xml
The documents folder needs to be a symlink or in some other way external from the war file because users will add and remove documents (through a mapped network drive).
I'd like to deploy the webapp as a war-file but I don't know how to do that and take the above into account. Could you give some pointers?
/Adam
If it's static content, maybe you'd be better off fronting your app server with a web server and putting the static content there. You relieve the app server of having to serve up static data and save a network roundtrip to boot.
I agree with #duffymo.myopenid.com that fronting your app server with a web server that serves static content for certain URL prefixes is a good, clean solution.
If this isn't feasible in your environment or if you decide that you'd rather handle it in the web application itself, you could write a servlet that effectively does the same thing. For example, create a servlet that is mapped to the URL pattern /documents/*. This servlet could parse the URL (/documents/some/file.png) to determine a relative filename (some/file.png). It could then read and return the corresponding contents found in an external directory (/staticDocs/some/file.png).
Why not store the documents etc. in a database, then have the web-app access the database and allow users to pull files that way? Does it have to be a mapped network drive?
Otherwise if it's a matter of knowing what is there, you could always construct the jnlp file dynamically and pass file lists, etc. in as arguments (if they are server side).
Guess we need to know a little more about what you are trying to accomplish.
Basically, it's a webapp that aggregates information from various sources and generates documents. It's a requirement that users have the ability to create and upload documents manually from the network without being logged in to the webapp.
Putting the document location path as a context variable is definately doable. I guess it's the easiest way. /Adam
Unfortunately, for you .war files are .zip files at heart and .zip files do not support symbolic links. If you are ONLY deploying to a windows machine you may have luck using a shortcut file. However, I'm not sure if the app-server will like that (... probably not.)
I would recommend adding a configuration parameter to the application that allows the document folder's full path to be specified there. The default path should be relative ("./www/files/documents") so that the app works out of the box without additional configuration.
Many java web servers support "exploded war files" where you just unzip your .war file into the deployment directory. With tomcat you copy this to $CATALINA_HOME/webapps and you're done.
This should work for you.
What about creating an environment variable on your server that points to the directory the files are stored in? The environment variable may work better than a setting inside your WAR file because you could deploy your application in a new environment (maybe moving from DEV to PROD) without changing your WAR file.
From your java code, you can reference this environment setting with:
String docPath= System.getProperty("DOC_PATH");
In Apache Tomcat it may sometimes be appropriate to achieve reuse via the tomcat RewriteValve like this:
META-INF/context.xml:
<Context>
<Valve className="org.apache.catalina.valves.rewrite.RewriteValve" />
</Context>
WEB-INF/rewrite.config:
RewriteRule (.*)/login(/.*\.)(png|jpg|js|css) $1$2$3
Now the /appContext/login/ path will use the same images/js/css as /appContext/
Of course as with all regular expression based solutions to ANY problem, keeping the complexity of the expression low is important for performance.
Sounds like you need a web Content Management System (CMS).