Search code examples
javahtmlpostgresqltomcat9

How to take user images, store them, and render them later?


I'm trying to build an application that takes a user image from an html form, uses a java servlet to store said image in a database, and then renders the image onto the screen with another html tag. The HTML form to accept the image is:

<form action="../servlets/submitrequest" method="post" enctype="multipart/form-data">
    <input type="number" name="cost" placeholder="Cost" required/><br/>
    <p id="img">Image of receipt: <input type="file" name="image" required/><br/></p> 
    <input type="submit" id="submit" name="submit" value="Submit" onClick="success();"/><br/>
</form>

The relevent part of my servlet that saves the file is:

Random r = new Random();

String dir = "C://tmp/reciepts/" + r.nextInt() + ".png";
        
for(Part part: request.getParts()) {
    if(part.getName().equalsIgnoreCase("image"))
        part.write(dir);
}

The servlet then saves dir as the image filepath in the database (postgresql). However when I tried to take the image URL and display it on the web browser Chrome throws the following error:

Not allowed to load local resource: file:///C://tmp/images/1154006734.png

Which according to this is caused because chrome can't read local files because of security reasons. Fair enough. So I started looking for ways to save it to the webcontent folder, so it would be a part of the content of the web application. I followed this example and changed my servlet's code to:

String dir = request.getServletContext().getRealPath("/") + File.separator + "reciepts";
File fileSaveDir = new File(dir);
if (!fileSaveDir.exists()) {
    fileSaveDir.mkdir();
}
request.getPart("image").write(dir);

Even after doing this I still received the same error:

Not allowed to load local resource: file:///C:/Users/Colby/eclipse-workspace/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/wtpwebapps/Project_1//reciepts/image.file

So my question is this: where do I store files uploaded by the user where they can be accessed by both the web browser and the application itself?


Solution

  • You have to change the doGet of a servlet to stream back the binary data.

    response.setContentType("application/pdf");
    
    try (
      ServletOutputStream output = response.getOutputStream();
      InputStream input = getServletContext().getResourceAsStream("myLocalFile.pdf");
    ){ 
      //transfer buffered stream to output stream
      byte[] buffer = new byte[2048];
      int bytesRead = -1;    
      while ((bytesRead = input.read(buffer)) != -1) {
         output.write(buffer, 0, bytesRead);
      }
    }
    

    Then in your HTML rather than having <img src...> pointing to a file have it pointing to the above servlet.

    note

    Of course when your web application is run from a remote user, then will have no knowledge or access to your server's file system directly.