留言板

Unable to download file using InputStream

Angeline Chan,修改在10 年前。

Unable to download file using InputStream

New Member 帖子: 3 加入日期: 12-2-21 最近的帖子
I currently use the following code to enable the user to download a file from an inputStream. I'm using Liferay 6.1 GA2 with JSF 2.0.

The file in question is an image which is only 1.33kb and I have no problems opening it from the server. It also displays fine in the xhtml page. However, when it is downloaded to the client computer using this code, it ends up as a 36.7 kb file. This downloaded file then can't be opened.

Even with an image of file size 558KB, the resulting downloaded file is also only 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();
		}


When I get the outputStream is the following manner:

		outputStream = response.getOutputStream(); 


I get the error saying that it's unable to get the Writer because the OutputStream is in use:

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


Does anyone have any idea what could be going wrong with this code?
Any help or push in the right direction will be greatly appreciated!
thumbnail
Vernon Singleton,修改在10 年前。

RE: Unable to download file using InputStream

Expert 帖子: 315 加入日期: 13-1-14 最近的帖子
There is just a slight mismatch between the part of the portlet lifecycle that your are using (the action phase) and the part of the portlet lifecycle that you are expecting to use (the resource phase). In order to better take advantage of the part of the lifecycle that you are expecting to be able to use, just take a quick look at the jsf2-export-pdf-portlet. This portlet uses something called a ResourceHandler to retreive a pdf document, where in your case it could be retreiving an image.

In the jsf2-export-pdf-portlet code here, you will find a method called getInputStream() containing code that is very similar to the code you showed above to get your InputStream.

The getInputStream method is one of the methods that you need to override when you are creating a ResourceHandler in a JSF application. You should find it to be straight forward to change the code n the jsf2-export-pdf-portlet to use the methods you are using to generate an InputStream following its ResourceHandler pattern, and generate a link to an image rather than a link to a pdf document.

Hope that helps. Let us know how you proceed after taking a look at the demo.

- Vernon
thumbnail
ALex joubert,修改在10 年前。

RE: Unable to download file using InputStream

Junior Member 帖子: 27 加入日期: 10-3-19 最近的帖子
Hi,
look here it may help you

https://www.liferay.com/community/forums/-/message_boards/message/24719404