0

I have a servlet which is used to display image.This servlet actually called by the

<img src="/displaySessionImage?widgetName=something"/>

My get & post redirect to this method,

protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    HttpSession session = request.getSession();
    String widgetName = request.getParameter("widgetName");     

    try {
                    //this is my file manager which was store ealier
        StorageFile file = (StorageFile)session.getAttribute(widgetName);      
        response.setContentType(file.getContentType());         

                    //the file manager can retrieve input stream
        InputStream in  = file.getInputStream();
        OutputStream outImage = response.getOutputStream();

        byte[]  buf   = new byte[1024];
        int     count = 0;
        while ((count = in.read(buf)) >= 0) {
            outImage.write(buf, 0, count);
        }


    } catch (Exception e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
 }

But this code does not work, the image could not be display. I think this will not work because i have store the file manager that contain the input stream in a session. This same method work for another image file that was retrieved from database and not stored in the session. i have actually print out the input stream. it contain the same input stream as the database file.

Is it something wrong with the code? or i actually cannot store the file manager that contain the input stream in a session? or is it that i used input stream in a wrong way?

Bhesh Gurung
  • 50,430
  • 22
  • 93
  • 142
Nur Aini
  • 393
  • 2
  • 5
  • 14
  • 1
    You need to elaborate more about what is actually happening. What exactly does this servlet return in response headers and body? (Firebug/Chrome/Fiddler2 can show it in detail). If it's throwing an exception, share the stacktrace. Last but not least, are you aware that most input streams can be read only once? – BalusC Dec 07 '11 at 03:23
  • @BalusC You are right, I shouldn't put my previous post as an answer, deleted it. As BalusC suggested, at least you can type the image URL in browser to see what you get, if there is any bytes received on the client side, or exceptions thrown on server side. If all go well, for conformance, I would set 'Content-Length' header too. – Jerry Tian Dec 07 '11 at 03:33
  • @BalusC i have a form which is use to upload file with other field like name, etc. I am using drag and drop for the file upload. Upon drag drop the file was store temporarily and the file manager object was created and stored in session to be retrieve when the whole form is submitted. If there is a field that is empty, the form will go back to the jsp. So i will need to display the picture on session exist. in the jsp there is the above img tag. the servlet actually just return itself as an image, in the header the content-type is already image/jpeg. no exception.lastly, im not aware of that – Nur Aini Dec 07 '11 at 03:43
  • Set content-length, and close the output stream. – Gabriel Belingueres Dec 07 '11 at 03:46
  • What do you mean with "servlet actually return itself as an image"? Do you see the servlet's source code in the response body or something? Please be more specific what the servlet actually returned. You said that it doesn't work, right? What does it return instead of the image? Anyway, again, are you aware that input streams can be read only once? I think that you don't realize/understand that. To start, store the image as `byte[]` in session instead and retry. If that works, then that explains it. – BalusC Dec 07 '11 at 03:47
  • @Gabriel: setting content length and closing output stream is not mandatory. – BalusC Dec 07 '11 at 03:48
  • @JerryTian when i type the image URL, it said that the image cannot be displayed because it contains error. but i dont have any exception thrown in the tomcat. – Nur Aini Dec 07 '11 at 03:50
  • @BalusC i am using firebug, response tab is empty, in header tab, response header contain : content-type : image/jpeg, content-length :0 , the server and the date. – Nur Aini Dec 07 '11 at 03:56
  • Ah, content length is 0? So the input stream was already read or implicitly closed/released. This confirms my initial guess. See my answer then. – BalusC Dec 07 '11 at 03:59
  • To all that response to this question, thank you very much. – Nur Aini Dec 07 '11 at 04:09
  • @NurAini, then I guess it may be the data itself that caused the problem. Using any download tools(I prefer wget and curl in Linux world) to download the image data, compare the MD5 sum with the data stored in database. Also, there is still a chance the data itself in database is corrupted, which needs more dig to find the reason and beyond the question here. – Jerry Tian Jan 13 '12 at 04:21

2 Answers2

0

Your code is not working because you are not able to display the uploaded image as your img syntax is wrong.

Try this:

<img src="${pageContext.request.contextPath}/submit/Java/2.jpg">

Here, /submit is the folder which is created in the project folder. I.e. this is the folder where all uploaded images are saved.

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • 1
    Probably you missed the part *"This same method work for another image file that was retrieved from database and not stored in the session"* in the original question which confirms that the URL is not the problem. By the way, you've there a major design problem with storing uploaded images in the project folder. Once you redeploy the webapp or even just restart the server, then you can say bye bye to all uploaded images. – BalusC Aug 23 '12 at 16:14
0

You are really not clear about what is actually happening, which is perhaps just ignorance. But storing and passing an InputStream around in the session is already not a good sign. Firstly, it is not serializable. Secondly, you're fully detaching the input stream from the context where it's been created (so it might implicitly have been closed/released when the initial context is finished). Thirdly, an input stream can often be read only once (so once it's read, it cannot be read again anymore, you'd have to create a new one).

The normal approach is to read the InputStream into a byte[] directly after its creation and then store that byte[] in the session instead.

InputStream input = uploadedFile.getInputStream();
ByteArrayOutputStream output = new ByteArrayOutputStream();
// Copy bytes from input to output the usual way.
// ...

byte[] content = output.toByteArray();
// Now store it in session.

And then in the image servlet, just do

// ...
response.getOutputStream().write(content);

You only need to be aware that each byte of a byte[] eats one byte of JVM's memory. Be sure that you don't go overboard. Remove the attribute from the session as soon as you don't need it anymore. Make use of temp file storage if necessary, for sure if you have to deal with large files.


Update: as per your comment on the question:

I am using firebug, response tab is empty, in header tab, response header contain : content-type : image/jpeg, content-length :0 , the server and the date.

A content length of 0 confirms that the input stream was already been read (or its source has implicitly been released). This only confirms my initial guesses. No, manually setting the content length header won't solve the problem. The servlet container already automatically takes care about it when the response body fits fully in the default response buffer; it would otherwise switch to chunked encoding anyway.

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • Thank you very much. as u said i am really not clear on how to used the input stream and the byte[]. Thanks for your help – Nur Aini Dec 07 '11 at 04:10