1

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

有问题的文件是一个只有 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)
    ...

任何帮助或推动正确方向将不胜感激!

4

1 回答 1

0

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

此处的 jsf2-export-pdf-portlet 代码中,您会发现一个名为 getInputStream() 的方法,其中包含的代码与您在上面显示的用于获取 InputStream 的代码非常相似。

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

希望有帮助。让我们知道您在查看演示后如何进行。

于 2013-09-10T15:12:17.467 回答