使用会话属性将servlet显示为img src

使用会话属性将servlet显示为img src

问题描述:

我有一个用于显示图像的servlet.

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?

您真的不清楚实际发生了什么,这可能只是无知.但是在会话中存储和传递InputStream已经不是一个好兆头.首先,它不可序列化.其次,您将输入流与创建它的上下文完全分离(因此,当初始上下文完成时,它可能隐式关闭/释放了).第三,输入流通常只能被读取一次(因此一旦被读取,就不能再被读取了,您必须创建一个新的输入流).

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).

通常的方法是在byte[]创建后直接将其读入byte[],然后将其存储在会话中.

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.

然后在图像servlet中,只需

And then in the image servlet, just do

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

您只需要知道byte[]的每个字节都占用JVM内存的一个字节.确保您不会过分.不再需要该属性时,请从会话中删除该属性.如有必要,请使用临时文件存储,以确保您必须处理大型文件.

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:

我正在使用Firebug,响应选项卡为空,在标头选项卡中,响应标头包含:content-type:image/jpeg,content-length:0,服务器和日期. >

内容长度为0确认输入流已被读取(或其源已隐式释放).这仅证实了我的最初猜测.不,手动设置内容长度标题不会解决问题.当响应主体完全适合默认响应缓冲区时,servlet容器已经自动进行处理.否则无论如何它都会切换为分块编码.

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.