10

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.

coding_idiot
  • 13,526
  • 10
  • 65
  • 116
Myy
  • 18,107
  • 11
  • 37
  • 57

3 Answers3

13

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:

Community
  • 1
  • 1
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • hey BalusC, this is exactly what I need. so please bare with me as thsi is the very first time I do somethign like this. the way I understand it: saving inside the proyect itself is a no-no because the files will be deleted once the WAR file is redeployed, that makes sense. so instead I will create a variable of a path inside teh server, and use that location to save the images. that path '/var/webapp/upload' is just a random path you chose, or is it a real path tomcats have? do I gointo my server's Computer>Properties>AdvancedSystemSettings>Environmentvariables>uservariables? – Myy Dec 15 '11 at 18:24
  • It's random, yes. It's free to your choice. The unix-style path `/var/webapp/upload` translates in Windows machines with server running on c:\ to `C:\var\webapp\upload`. As to specifying the VM argument, edit Tomcat's `startup.bat` or Tomcat's Window service properties or add it as `JAVA_OPTS` environment variable. – BalusC Dec 15 '11 at 18:26
  • Ok, I got it to store teh images in the server, yay!, now to display it. I don't quite understand about the you know how in a regular xhtml to display an image you put click to Add a photo well, how do I referece the C:\uploads folder? since teh picture will avry depending on which profile I'm on, am I going to need to use a servlet to display it? – Myy Dec 15 '11 at 19:14
  • Add `` to Tomcat's `/conf/server.xml` and use ``. This way Tomcat's own `DefaultServlet` will serve it. See also "Reliable data serving" link at the bottom of my answer. – BalusC Dec 15 '11 at 19:16
  • ok, I've found the folder with the file and I've updated it. and it works fine. but for some reason , it looks like every time I restart the server, the file changes back to its original self, and it doesn't contain the new I put in. – Myy Dec 16 '11 at 07:35
  • Then you're using an IDE like Eclipse which has taken over control from Tomcat and supplies its own copy of `server.xml`. You should actually not use an IDE to take over control of a production server, but ala, you need to edit the `server.xml` as available in IDE's *Servers* project instead of Tomcat's own one. – BalusC Dec 16 '11 at 09:59
  • oh ok, so i now changed the server.xml IN my servers folder IN my Eclipse. And everything seems ot be working fine. Thanks a lot balusC and Merry Xmas – Myy Dec 23 '11 at 02:04
  • @BaluC: Hey, I have the same setup but image does not show up....when I try giving http://localhost:8080/image/image.jpg it shows me resource not available error any idea what am I doing wrong? – Sudh Dec 14 '12 at 03:37
  • I have /static/* mapped to default server in my servlet.xml file can that be causing issue? – Sudh Dec 14 '12 at 04:08
  • 1
    for everyone else like me, who don't know where to create the element in the server.xml - you have to create it within the tag. – coding_idiot Jan 13 '13 at 11:39
  • @XCoder: that's indeed explained as such in [Tomcat documentation](http://tomcat.apache.org/tomcat-7.0-doc/config/context.html) for the case you're editing `server.xml` instead of creating `context.xml`. – BalusC Jan 13 '13 at 13:18
  • @BalusC if i do like this, what will be the url that i need to use to access this images using glide so that i can display it in an imageview??? – KJEjava48 Apr 10 '17 at 08:54
2

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:

  1. 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.
  2. The availability guaranteed by storing it on S3 is probably better then what you would get by storing it on your own Windows box.
  3. 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.)
Wilfred Springer
  • 10,869
  • 4
  • 55
  • 69
-3

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.

belgther
  • 2,544
  • 17
  • 15