Search code examples
javaservletsglassfish-3multipartform-dataservlet-3.0

Glassfish - uploading images - doing it right


I am on latest glassfish (3.1.2) - so no need for apache FileItem and no bugs with getPart(). I read that the best practice on uploading images is saving them on the file system (see here for instance). I am editing already existing code - smelly at that - so I had the idea to do :

Part p1 = request.getPart("file");
System.out.println("!!!!!P1 : " + p1);

Prints :

!!!!!P1 : File name=DSC03660.JPG, 
StoreLocation=C:\_\glassfish3\glassfish\domains\domain1\generated\jsp\elkethe\upload_7cb06306_138b413999a__7ffa_00000000.tmp, 
size=2589152bytes, isFormField=false, FieldName=file

newlines mine. In the code people are doing :

if (request.getParameter("crop") != null) {
    // get path on the server
    String outputpath = this.getServletContext().getRealPath(
            "images/temp/" + session.getId() + ".jpg");
    // store photo
    InputStream is = p1.getInputStream();
    createPhoto(is, outputpath);
    session.setAttribute("photo_path", "images/temp/" + session.getId()
            + ".jpg");
    response.sendRedirect("cropping");
    return;
}

Where

private void createPhoto(InputStream is, String outputpath) {
    FileOutputStream os = null;
    try {
        os = new FileOutputStream(outputpath);
        // write bytes taken from uploaded file to target file
        int ch = is.read();
        while (ch != -1) {
            os.write(ch);
            ch = is.read();
        }
    } catch (Exception ex) {
        ex.printStackTrace();
    } finally {
        Helpers.close(os);
    }
}

Now what happens is that the file is uploaded in the StoreLocation (???) on submitting the form so apparently all this p1.getInputStream() is for naught.

My questions are :

  • what is StoreLocation ? How tmp are those glassfish uploads ? Where are all those parameters set ? I did read BalusC' tutorial - but there is no mention of StoreLocation (google is not very helpful either).
  • What would be a more professional way of handling the situation - including keeping the photos outside the webroot - but using facilities glassfish provides (if it does provide) ?
  • Even p1 printing so nice escapes me (it does not seem to Override toString())

Interested in tips even in how should one rename the photos etc (is this sessionID thing Right ? - check also the time trick) :

if (request.getParameter("save") != null) {
    long time = System.currentTimeMillis();
    String path = "images/upload/" + session.getId() + time + ".jpg";
    String outputpath = this.getServletContext().getRealPath(path);
    // store photo
    InputStream is = p1.getInputStream();
    createPhoto(is, outputpath);
    // etc
}

Solution

  • What is StoreLocation ? How tmp are those glassfish uploads ? Where are all those parameters set ?

    StoreLocation is just the the java.io.File object for the FileItem's data's temporary location on the disk. Resides in javax.servlet.context.tempdir which defaults to %GLASSFISH_HOME%\domains\domain1\generated\jsp\webApp. Those uploads are as tmp as anything (The lifetime of the file is tied to the lifetime of the FileItem instance; the file will be deleted when the instance is garbage collected - from here). Haven't yet managed to change the value of javax.servlet.context.tempdir programmatically (comment please) - it is the tempdir property of the sun-web-app element of the sun-web.xml.

    What would be a more professional way of handling the situation - including keeping the photos outside the webroot - but using facilities glassfish provides (if it does provide) ?

    Well a more professional way is to Use Part.write() to move the file to the desired location. Due to glassfish implementation though you can't supply an absolute path to write - a chore. I asked here.

    As to where to save the file : https://stackoverflow.com/a/18664715/281545

    That is for saving the file - to serve it from a location outside the app you need to define "alternatedocroot" properties in the sun-web.xml (or glassfish-web.xml).

    Even p1 printing so nice escapes me (it does not seem to Override toString())

    Oh yes it does

    Interested in tips even in how should one rename the photos etc (is this sessionID thing Right ? - check also the time trick)

    No it is not - I tend towards File#createTempFile() - anyway this is a different question asked here