Uploaded image only available after refreshing the page

When I upload a picture, the file is successfully saved and the path is successfully set. But the uploaded image is not displayed immediately after the form submit. Only when I reload the page, the uploaded image is displayed.

I'm saving the uploaded file as below:

InputStream is;
try {
    File file = new File("C:\\****\\*****\\Documents\\NetBeansProjects\\EventsCalendary\\web\\resources\\images\\uploadPhoto.png");
    is = event.getFile().getInputstream();
    OutputStream os = new FileOutputStream(file);
    setUserPhoto("\\EventsCalendary\\resources\\images\\"+file.getName());   
    byte buf[] = new byte[1024];
    int len;
    while ((len = is.read(buf)) > 0) {
        os.write(buf, 0, len);
    }
    os.close();
    is.close();

} catch (IOException ex) {
    System.out.println(ex.getStackTrace());
}

Why is the uploaded image only displayed after reloading the page and how can I solve this?


Solution 1:

You're writing the file straight into the IDE's project folder and your intent seems to save the file in the webapp's deploy folder. This is a bad idea and well due to the following 3 main reasons:

  1. Changes in the IDE's project folder does not immediately get reflected in the server's work folder. There's kind of a background job in the IDE which takes care that the server's work folder get synced with last updates (this is in IDE terms called "publishing"). This is the main cause of the problem you're seeing.

  2. In real world code there are circumstances where storing uploaded files in the webapp's deploy folder will not work at all. Some servers do (either by default or by configuration) not expand the deployed WAR file into the local disk file system, but instead fully in the memory. You can't create new files in the memory without basically editing the deployed WAR file and redeploying it.

  3. Even when the server expands the deployed WAR file into the local disk file system, all newly created files will get lost on a redeploy or even a simple restart, simply because those new files are not part of the original WAR file.

You need to write it to a fixed path outside the project/deploy folder instead. For example, /var/webapp/uploads. Then, to get it to be served by your webapp, just add it as a new web application context to the server.

Based on your previous question, I know that you're using Glassfish 3.1. In this server, it's called a "virtual host". You can configure it at server level in the admin console at http://localhost:4848 > Configuration > HTTP Service > Virtual Servers, or at webapp level by adding the following line to the /WEB-INF/glassfish-web.xml (your IDE should have autogenerated one; note that this file is before Glassfish 3.1 called sun-web.xml, so if you're seeing manuals/blogs/tutorials referencing it, yes it's exactly the same file):

<property name="alternatedocroot_1" value="from=/uploads/* dir=/var/webapp" />

Either way, you should then be able to use http://localhost:8080/contextname/uploads/* to serve those uploaded images from by <img> the usual way.

See also:

  • How to upload files to server using JSP/Servlet?
  • Recommended way to save uploaded files in a servlet application (contains a Tomcat configuration example)
  • Reading/writing a text file in a servlet, where should this file be stored in JBoss? (contains JBoss configuration example)
  • Simplest way to serve static data from outside the application server in a Java web application