[RESOLVIDO] Servlet response already use Writer, OutputStream not possible

Bom dia pessoal,

estou fazendo uma função para download na aplicação que estou trabalhando. Segue o código:

[code]public String download() throws IOException {

	Attachment attachment = AttachmentDao.find(idAttachment,entityManager);
	if(attachment==null) {
		return "File not found.";
	}
	
	byte[] data = AttachmentUtil.getPhisicalAttachment(attachment); 
			
	HttpServletResponse response = (HttpServletResponse) extCtx.getResponse();
	response.setContentType(attachment.getContentType());
	response.addHeader("Content-disposition", "attachment; filename=" + attachment.getName() +"\"");
    response.setContentLength(data.length);
    
    //nesta linha ocorre o erro
    ServletOutputStream os = response.getOutputStream();
	os.write(data);
	os.flush();
	os.close();
	
	facesContext.responseComplete();
	return null;
	
}[/code]

Porem estou com dificuldade para criar essa função, pois me retorna o seguinte erro:
Alguém poderia me ajudar dando uma luz de como resolver isso? Grato.

12:34:00,951 GRAVE [facelets.viewhandler] Error Rendering View[/DownloadAttachment.xhtml]: javax.faces.FacesException: javax.el.ELException: /DownloadAttachment.xhtml @9,59 value="#{downloadAttachment.download()}": java.lang.IllegalStateException: Servlet response already use Writer, OutputStream not possible
	at javax.faces.component.UIOutput.getValue(UIOutput.java:187) [:1.2_15-20100816-SNAPSHOT]
	at com.sun.faces.renderkit.html_basic.HtmlBasicInputRenderer.getValue(HtmlBasicInputRenderer.java:201) [:1.2_15-20100816-SNAPSHOT]
	at com.sun.faces.renderkit.html_basic.HtmlBasicRenderer.getCurrentValue(HtmlBasicRenderer.java:287) [:1.2_15-20100816-SNAPSHOT]
	at com.sun.faces.renderkit.html_basic.HtmlBasicRenderer.encodeEnd(HtmlBasicRenderer.java:154) [:1.2_15-20100816-SNAPSHOT]
	at javax.faces.component.UIComponentBase.encodeEnd(UIComponentBase.java:864) [:1.2_15-20100816-SNAPSHOT]
	at javax.faces.component.UIComponent.encodeAll(UIComponent.java:937) [:1.2_15-20100816-SNAPSHOT]
	at javax.faces.component.UIComponent.encodeAll(UIComponent.java:933) [:1.2_15-20100816-SNAPSHOT]
	at com.sun.facelets.FaceletViewHandler.renderView(FaceletViewHandler.java:592) [:2.2.2.Final]
	at org.ajax4jsf.application.ViewHandlerWrapper.renderView(ViewHandlerWrapper.java:100) [:3.3.3.Final]
	at org.ajax4jsf.application.AjaxViewHandler.renderView(AjaxViewHandler.java:176) [:3.3.3.Final]
	at com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:110) [:1.2_15-20100816-SNAPSHOT]
	at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:100) [:1.2_15-20100816-SNAPSHOT]
	at com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:139) [:1.2_15-20100816-SNAPSHOT]
	at javax.faces.webapp.FacesServlet.service(FacesServlet.java:266) [:1.2_15-20100816-SNAPSHOT]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:324) [:6.1.0.Final]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:242) [:6.1.0.Final]
	at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:83) [:2.2.2.Final]
	at org.jboss.seam.web.IdentityFilter.doFilter(IdentityFilter.java:40) [:2.2.2.Final]
	at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69) [:2.2.2.Final]
	at org.jboss.seam.web.MultipartFilter.doFilter(MultipartFilter.java:90) [:2.2.2.Final]
	at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69) [:2.2.2.Final]
	at org.jboss.seam.web.ExceptionFilter.doFilter(ExceptionFilter.java:64) [:2.2.2.Final]
	at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69) [:2.2.2.Final]
	at org.jboss.seam.web.RedirectFilter.doFilter(RedirectFilter.java:45) [:2.2.2.Final]
	at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69) [:2.2.2.Final]
	at org.ajax4jsf.webapp.BaseXMLFilter.doXmlFilter(BaseXMLFilter.java:206) [:3.3.3.Final]
	at org.ajax4jsf.webapp.BaseFilter.handleRequest(BaseFilter.java:290) [:3.3.3.Final]
	at org.ajax4jsf.webapp.BaseFilter.processUploadsAndHandleRequest(BaseFilter.java:388) [:3.3.3.Final]
	at org.ajax4jsf.webapp.BaseFilter.doFilter(BaseFilter.java:515) [:3.3.3.Final]
	at org.jboss.seam.web.Ajax4jsfFilter.doFilter(Ajax4jsfFilter.java:56) [:2.2.2.Final]
	at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69) [:2.2.2.Final]
	at org.jboss.seam.servlet.SeamFilter.doFilter(SeamFilter.java:158) [:2.2.2.Final]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:274) [:6.1.0.Final]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:242) [:6.1.0.Final]
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:275) [:6.1.0.Final]
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:161) [:6.1.0.Final]
	at org.jboss.web.tomcat.security.SecurityAssociationValve.invoke(SecurityAssociationValve.java:181) [:6.1.0.Final]
	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:501) [:6.1.0.Final]
	at org.jboss.web.tomcat.security.JaccContextValve.invoke(JaccContextValve.java:88) [:6.1.0.Final]
	at org.jboss.web.tomcat.security.SecurityContextEstablishmentValve.invoke(SecurityContextEstablishmentValve.java:100) [:6.1.0.Final]
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:159) [:6.1.0.Final]
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102) [:6.1.0.Final]
	at org.jboss.web.tomcat.service.jca.CachedConnectionValve.invoke(CachedConnectionValve.java:158) [:6.1.0.Final]
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109) [:6.1.0.Final]
	at org.jboss.web.tomcat.service.request.ActiveRequestResponseCacheValve.invoke(ActiveRequestResponseCacheValve.java:53) [:6.1.0.Final]
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:362) [:6.1.0.Final]
	at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:877) [:6.1.0.Final]
	at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:654) [:6.1.0.Final]
	at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:951) [:6.1.0.Final]
	at java.lang.Thread.run(Unknown Source) [:1.6.0_45]
Caused by: javax.el.ELException: /DownloadAttachment.xhtml @9,59 value="#{downloadAttachment.download()}": java.lang.IllegalStateException: Servlet response already use Writer, OutputStream not possible
	at com.sun.facelets.el.TagValueExpression.getValue(TagValueExpression.java:76) [:1.1.15.B1]
	at javax.faces.component.UIOutput.getValue(UIOutput.java:184) [:1.2_15-20100816-SNAPSHOT]
	... 49 more
Caused by: java.lang.IllegalStateException: Servlet response already use Writer, OutputStream not possible
	at org.ajax4jsf.webapp.FilterServletResponseWrapper.getOutputStream(FilterServletResponseWrapper.java:226) [:3.3.3.Final]
	at javax.servlet.ServletResponseWrapper.getOutputStream(ServletResponseWrapper.java:140) [:1.0.0.Final]
	at sunseterp.session.components.attachment.DownloadAttachment.download(DownloadAttachment.java:54) [:]
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) [:1.6.0_45]
	at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) [:1.6.0_45]
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) [:1.6.0_45]
	at java.lang.reflect.Method.invoke(Unknown Source) [:1.6.0_45]
	at org.jboss.seam.util.Reflections.invoke(Reflections.java:22) [:2.2.2.Final]
	at org.jboss.seam.intercept.RootInvocationContext.proceed(RootInvocationContext.java:32) [:2.2.2.Final]
	at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:56) [:2.2.2.Final]
	at sunseterp.session.interceptor.SunsetTransactionInterceptor.aroundInvoke(SunsetTransactionInterceptor.java:27) [:]
	at sun.reflect.GeneratedMethodAccessor678.invoke(Unknown Source) [:1.6.0_45]
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) [:1.6.0_45]
	at java.lang.reflect.Method.invoke(Unknown Source) [:1.6.0_45]
	at org.jboss.seam.util.Reflections.invoke(Reflections.java:22) [:2.2.2.Final]
	at org.jboss.seam.intercept.Interceptor.aroundInvoke(Interceptor.java:187) [:2.2.2.Final]
	at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:72) [:2.2.2.Final]
	at org.jboss.seam.transaction.RollbackInterceptor.aroundInvoke(RollbackInterceptor.java:28) [:2.2.2.Final]
	at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:68) [:2.2.2.Final]
	at org.jboss.seam.core.BijectionInterceptor.aroundInvoke(BijectionInterceptor.java:77) [:2.2.2.Final]
	at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:68) [:2.2.2.Final]
	at org.jboss.seam.core.MethodContextInterceptor.aroundInvoke(MethodContextInterceptor.java:44) [:2.2.2.Final]
	at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:68) [:2.2.2.Final]
	at org.jboss.seam.intercept.RootInterceptor.invoke(RootInterceptor.java:107) [:2.2.2.Final]
	at org.jboss.seam.intercept.JavaBeanInterceptor.interceptInvocation(JavaBeanInterceptor.java:185) [:2.2.2.Final]
	at org.jboss.seam.intercept.JavaBeanInterceptor.invoke(JavaBeanInterceptor.java:103) [:2.2.2.Final]
	at sunseterp.session.components.attachment.DownloadAttachment_$$_javassist_seam_35.download(DownloadAttachment_$$_javassist_seam_35.java) [:]
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) [:1.6.0_45]
	at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) [:1.6.0_45]
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) [:1.6.0_45]
	at java.lang.reflect.Method.invoke(Unknown Source) [:1.6.0_45]
	at org.jboss.el.util.ReflectionUtil.invokeMethod(ReflectionUtil.java:335) [:1.0_02.CR5]
	at org.jboss.el.util.ReflectionUtil.invokeMethod(ReflectionUtil.java:280) [:1.0_02.CR5]
	at org.jboss.el.parser.AstMethodSuffix.getValue(AstMethodSuffix.java:59) [:1.0_02.CR5]
	at org.jboss.el.parser.AstValue.getValue(AstValue.java:67) [:1.0_02.CR5]
	at org.jboss.el.ValueExpressionImpl.getValue(ValueExpressionImpl.java:186) [:1.0_02.CR5]
	at com.sun.facelets.el.TagValueExpression.getValue(TagValueExpression.java:71) [:1.1.15.B1]
	... 50 more

Isso acontece porque a resposta só pode ser escrita uma vez. Se alguém já escreveu algo na Stream de saída você não consegue reescrever o response.

Eu acredito que no seu caso o próprio JSF já utilizou o writer, e então você não pode fazer o que quer, eu sugiro que procure algum componente do JSF específico para downloads, eu sei que o PrimeFaces tem um.

Experimenta este código abaixo:


protected void enviarArquivo(String nomeDoc, byte[] conteudo) throws IOException {

	this.getResponse().reset();
	this.getResponse().setContentType("application/download charset=utf-8");
	//set header name
	this.getResponse().setHeader("Content-Disposition", "attachment; filename=" + nomeDoc);
	this.getResponse().setHeader("Cache-Control", "no-cache");
	this.getResponse().setStatus(HttpServletResponse.SC_OK);

	this.getResponse().getOutputStream().write(conteudo);
	this.getResponse().getOutputStream().close();
	this.getFacesContext().responseComplete();

}


public FacesContext getFacesContext() {
	return FacesContext.getCurrentInstance();
}

public HttpServletResponse getResponse() {
	return (HttpServletResponse) this.getExternalContext().getResponse();
}

public ExternalContext getExternalContext() {
	return FacesContext.getCurrentInstance().getExternalContext();
}

Para pdf uso assim:


protected void enviarPdf(String nomeDoc, byte[] conteudo) throws IOException {

	this.getResponse().reset();
	this.getResponse().setContentType("application/pdf charset=utf-8");
	//set header name
	this.getResponse().setHeader("Content-Disposition", "attachment; filename=" + nomeDoc + ".pdf");
	this.getResponse().setHeader("Cache-Control", "no-cache");
	this.getResponse().setStatus(HttpServletResponse.SC_OK);

	this.getResponse().getOutputStream().write(conteudo);
	this.getResponse().getOutputStream().close();
	this.getFacesContext().responseComplete();

}


public FacesContext getFacesContext() {
	return FacesContext.getCurrentInstance();
}

public HttpServletResponse getResponse() {
	return (HttpServletResponse) this.getExternalContext().getResponse();
}

public ExternalContext getExternalContext() {
	return FacesContext.getCurrentInstance().getExternalContext();
}

Bom dia pessoal, obrigado pela ajuda, consegui resolver o problema da seguinte forma:

Criei um servlet como mostrado abaixo.

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet(name = "DownloadFile", urlPatterns = "/download_file")
public class DownloadFile extends HttpServlet {
	
	/**
	 * 
	 */
	private static final long serialVersionUID = -8634999872127869071L;
	
	
	protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		
		String path = request.getParameter("pathFile");
		
		String nameFile = path.substring(path.lastIndexOf("/")+1);
		
		OutputStream os = response.getOutputStream();
		
		File file = new File(path);
		FileInputStream fis = new FileInputStream(file);
		
		response.setHeader ("Content-Disposition", "attachment; filename=" +  nameFile);
		response.setContentLength((int) file.length());
		
		BufferedInputStream buf = new BufferedInputStream(fis);
		int readBytes = 0;
		
		while((readBytes = buf.read()) != -1) {
			os.write(readBytes);
		}
		os.flush();
		os.close();
		buf.close();
		
	}
	
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		processRequest(req, resp);
	}
	
	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		processRequest(req, resp);
	}
	
	@Override
    public String getServletInfo() {
        return "Short description";
    }
	
}

e depois no meu arquivo xhtml faço a chamada a esse servlet desta forma:

<a href="/download_file?pathFile=#{_file.completePath}">
<img src="/img/arrow_down.png" width="16px" height="16px" align="absmiddle" title="#{messages['Baixar']}" />
</a>

Assim consigo ter controle completo da resposta podendo usar o outputStream para escrever o arquivo.

Agradeço novamente a quem ajudou.

Alan

Servlet sempre judia :slight_smile: