Download de arquivo com OutputStream ou PrintWriter?

Boa Tarde,
Desenvolvi uma app web(JSF2.0 e PrimeFaces) que em determinada pagina o usuário pode fazer o download de um arquivo ZIP:

public String download(File arquivo, String tipo){
		if(arquivo.exists()){
			FacesContext facesContext = FacesContext.getCurrentInstance();  

			facesContext.getExternalContext().getRequest();  
			HttpServletResponse response = (HttpServletResponse) facesContext.getExternalContext().getResponse();  
			OutputStream os = null;  

			byte[] arquivoGerado= new ConverteArquivo().recuperaFileEmByte(arquivo);

			try {  
				os = response.getOutputStream();  
				response.setContentType("application/"+tipo);  
				response.setContentLength(arquivoGerado.length);  
				response.setHeader("Content-disposition","attachment; filename="+arquivo.getName());  
				os.write(arquivoGerado); 
			} catch (Exception e) {  
				e.printStackTrace();
			} finally{  
				try {  
					if(os != null){  
						os.flush();  
						os.close();  
					}  
					facesContext.responseComplete();  
				} catch (IOException e) {  
					e.printStackTrace();

				}  
			}  
			return "download.xhtml?faces-redirect=true";
		}else{

			return "arquivoNaoExiste.xhtml?faces-redirect=true";	
		}
	}

Esse codigo usa o OutputStream, e ao ser executado ele me gera uma

java.lang.IllegalStateException: getOutputStream() has already been called for this response

Dei uma pesquisada e descobri que isso é gerado por causa do JSP que faz um getWriter() para mandar o texto html.

Por isso usei o PrintWriter:

public String download(File arquivo, String tipo){
		if(arquivo.exists()){
			FacesContext facesContext = FacesContext.getCurrentInstance();  

			facesContext.getExternalContext().getRequest();  
			HttpServletResponse response = (HttpServletResponse) facesContext.getExternalContext().getResponse();  
			OutputStream os = null;  

			//byte[] arquivoGerado= new ConverteArquivo().recuperaFileEmByte(arquivo);

			try {  
				//os = response.getOutputStream();  
				response.setContentType("application/"+tipo);  
				//response.setContentLength(arquivoGerado.length);  
				response.setHeader("Content-disposition","attachment; filename="+arquivo.getName());  
				InputStream in = new FileInputStream(arquivo);
				PrintWriter output = response.getWriter();
				int bit = 256;
				while ((bit) >= 0) {
					bit = in.read();
					output.write(bit);
				}

			} catch (Exception e) {  
				e.printStackTrace();
			} finally{  
				try {  
					if(os != null){  
						os.flush();  
						os.close();  
					}  
					facesContext.responseComplete();  
				} catch (IOException e) {  
					System.out.println("2");  

				}  
			}  
			return "download.xhtml?faces-redirect=true";
		}else{

			return "arquivoNaoExiste.xhtml?faces-redirect=true";	
		}

Porem, esse codigo me gera uma:

java.net.SocketException: Software caused connection abort: socket write error

Ambos funcionam apesar das exceptions, porem qual seria uma solução mais elegante a ser usada nesse caso, o Output ou PrintWriter?

ps. Poderia ter usado o h:outputlink porem perderia a função de validar se o arquivo existe ou não.

Caso não tenha ficado muito claro a duvida posso tentar ilustrar de outra maneira

Desde ja agradeço :smiley:

quando vc dá um response.getOutputStream().write
vc tem q retornar sua página null, não dá pra retornar os 2 ao mesmo tempo

no lugar disso
return “download.xhtml?faces-redirect=true”;
coloque isso
return null;

talvez seja isso
falow

porque vc nao usa o componente de FileDownload do primefaces? é muito simples de usar

[]'s

Edi, no demo do PrimeFaces ele não seta o StreamedContent somente? e o próprio Primefaces sabe qual atributo buscar pra fazer o download.

Pelo menos é assim que é feito aqui. não abrimos Writers na mão.

eduJava
eu não retorno duas vezes, se o arquivo existe no server eu faço o download e retorno para a pagina de downloads se ele não existe eu retorno para uma pagina falando q o arquivo não existe.

mauricioadl
Não uso o FileDownload pq ele, igual ao outPutLink do JSF, não dão a possibilidade de validar se o arquivo existe ou não… se eu coloco um link diretor(FileDownload) e o arquivo não existe ele redireciona o usuário para uma pagina de erro do próprio server, não fica muito “bonito” hehe

digaoneves
Fala senhor Sasaki, coma vai?

Vou testar um pouco do prime, ver se consigo fazer para varios arquivos…

VLwwww

brother acho q vc não entendeu, quando vc faz o write vc não pode direcionar pra pagina nenhuma, pois seu response ja foi feito, se ligou?
ou vc muda de pagina ou vc volta o arquivo pro cara fazer o download
experimente colocar seus returns só pra teste, coloque null nos 2 returns, o erro deve sumir
falow

desculpe só troque o return de dentro
return “download.xhtml?faces-redirect=true” por return null