无法使用InputStream下载文件

时间:2013-09-06 07:34:40

标签: file jsf jsf-2 download liferay-6

我目前使用以下代码使用户能够从inputStream下载文件。我正在使用Liferay 6.1 GA2和JSF 2.0。

有问题的文件是一张只有1.33kb的图片,我从服务器打开它没有任何问题。它也在xhtml页面中显示正常。但是,当使用此代码将其下载到客户端计算机时,它最终会成为36.7 kb的文件。然后无法打开此下载的文件。

即使文件大小为558KB的图像,生成的下载文件也只有36.7kb。

    FacesContext facesContext = FacesContext.getCurrentInstance();
    OutputStream outputStream = null;

    try{
        ExternalContext externalContext = facesContext.getExternalContext();
        ActionResponse actionResponse = (ActionResponse) externalContext.getResponse();
        HttpServletResponse response = PortalUtil.getHttpServletResponse(actionResponse);

        outputStream = externalContext.getResponseOutputStream();

        //Set the information needed in the response
        String contentType = MimeTypesUtil.getContentType(fileName);
        response.reset(); 
        response.setBufferSize(BUFFER_SIZE);
        externalContext.setResponseBufferSize(BUFFER_SIZE);
        response.setContentType(contentType); 
        response.setContentLength((int)fileSize);
        response.setHeader("Content-disposition", "attachment; filename=\"" + fileName + "\"");

        InputStream inputStream = getImageInputStream();

        int read = 0;
        byte[] bytes = new byte[BUFFER_SIZE];

        int count = 0;
        while ((read = inputStream.read(bytes)) != -1) {
          count++;
          outputStream.write(bytes, 0, read);
        }

        //The following always outputs the right size
        System.out.println("Wrote " + count + "x" + BUFFER_SIZE + "b");

    } catch (Exception ex){
        ex.printStackTrace();
    } finally {
        if (outputStream != null)
            IOUtils.closeQuietly(outputStream);
        facesContext.responseComplete();
    }

有没有人知道这段代码会出现什么问题?

尝试了其他代码

我也尝试使用此代码设置响应数据。页面自行刷新,方法被调用,但没有下载文件。

    String contentType = MimeTypesUtil.getContentType(fileName);
    externalContext.responseReset();
    externalContext.setResponseBufferSize(BUFFER_SIZE);response.setContentType(contentType);
    externalContext.setResponseContentLength((int)fileSize);
    externalContext.setResponseHeader("Content-disposition", "attachment; filename=\"" + fileName + "\"");

当我得到outputStream时,采用以下方式:

    outputStream = response.getOutputStream(); 

我收到错误,说它无法获取Writer,因为OutputStream正在使用中:

java.lang.IllegalStateException: Cannot obtain Writer because OutputStream is already in use
    com.liferay.portal.kernel.servlet.StringServletResponse.getWriter(StringServletResponse.java:102)
    org.apache.jasper.runtime.JspWriterImpl.initOut(JspWriterImpl.java:125)
    org.apache.jasper.runtime.JspWriterImpl.write(JspWriterImpl.java:221)
    org.apache.jsp.html.common.themes.portal_jsp._jspService(portal_jsp.java:297)
    org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
    org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:432)
    org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:390)
    org.apache.jasper.servlet.JspServlet.service(JspServlet.java:334)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
    com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilterChain.doFilter(InvokerFilterChain.java:72)
    ...

非常感谢任何帮助或推动正确的方向!

1 个答案:

答案 0 :(得分:0)

您正在使用的portlet生命周期部分(操作阶段)与您期望使用的portlet生命周期部分(资源阶段)之间存在轻微的不匹配。为了更好地利用您期望能够使用的生命周期的一部分,只需快速查看jsf2-export-pdf-portlet。这个portlet使用一个称为ResourceHandler的东西来检索pdf文档,在这种情况下,它可能会重新获取图像。

the jsf2-export-pdf-portlet code here中,您将找到一个名为getInputStream()的方法,其中包含的代码与您上面显示的用于获取InputStream的代码非常相似。

getInputStream方法是在JSF应用程序中创建ResourceHandler时需要覆盖的方法之一。您应该发现直接更改jsf2-export-pdf-portlet中的代码以使用您用于在其ResourceHandler模​​式之后生成InputStream的方法,并生成指向图像reather的链接而不是指向a的链接。 pdf文件。

希望有所帮助。在taking a look at the demo之后告诉我们您的行为。