Help with the error: can not call getOutputStream () after getWriter (), when trying to perform a file download in java?

1

I have the following method in the controller, which returns a json type response to the view, to show in a dialog whether or not there is data in the bd according to the information of the parameters that happened to my service.

	
@RequestMapping(value="view/obtieneInfo")
@ResponseStatus(HttpStatus.OK)
@ResponseBody
public  JsonResponse obtieneInfor(@ResponseBody Factura fact, HttpServletRequest request, HttpServletResponse respons) throws ControlException{

JsonResponse response = new JsonResponse();
response.setExito(0);
response.setDatos(null);

try{
List<Factura> factList = obtieneInfoService.consultaDatos(id, cvePag, fecha);
if(factList !=null && !factList.isEmpty){
 response.setExito(1);
 response.setDatos(factList);

}else{
  log.info("Esta vacio");
}
}catch(ControlException e){
   throw new ControlException("Error", e);
}
return response;
}

This is my view code, which validates fields and when the fields are filled and the button is clicked, those parameters are passed to the service, and a dialog is sent to inform if there is data or not, and if you have to download a file with these data

<script>

function consultar(){
var valido = true;
var valId = document.getElementaryById('idPago').value;
var valClavePago = document.getElementaryById('clavePago').value;
var valFecha = document.getElementaryById('fechaPago').value;

if(valId.trim() =="" && valClavePago.trim() == "" && valFecha.trim() == ""){

  HelperDialogs.mostrar("Debes ingresar al menos un valor");
  valido = false;
}
  return valido;
}



function obtieneInf(){
	if(consultar()){
		if(!HelperForm.valido(consulta, validator)){
			return;
			
		}else{
			
			var data = Helper.obtenerJsonForm(consulta);
			var url="${pageContext.request.contextPath}/view/obtieneInfo";
			$.ajax({
				type:"POST",
				contentType: "application/json",
				url: url,
				data: data,
				dataType: 'json',
			success: function(response){
				if(response.exito==1){
					HelperDialogo.mostrar("Si hay registros");
				}else{
					HelperDialogo.mostrar("No se encontraron registros");
				}

			},
			error: function(response){
				HelperDialogo.mostrarError(response);
			}

			});
		}
	}
}
</script>
<form:form id="consulta" modelAttribute="consultaForm">
  <tr>
    <td><label>ID/label></td>
    <td><form: input type="text"  id="idPago" path="id"/></td>
   </tr>
   
   <tr>
    <td><label>CLAVE PAGO</label></td>
    <td><form: input type="text" id="clavePago" path="clavePago"/></td>
   </tr>
   
   <tr>
   
   
   <tr>
    <td><label>FECHA PAGO</label></td>
    <td><form: input type="text" id="fechaPago" path="fechaPago"/></td>
    <input type="button" onclick="obtieneInf()"></input>
   </tr>
</form:form>

And it does it correctly, the problem arises when you add the code to make the download of a file with the information that returns the query, the code looks like this:

@RequestMapping(value="view/obtieneInfo")
@ResponseStatus(HttpStatus.OK)
@ResponseBody
public  JsonResponse obtieneInfor(@ResponseBody Factura fact, HttpServletRequest request, HttpServletResponse respons) throws ControlException{

JsonResponse response = new JsonResponse();
response.setExito(0);
response.setDatos(null);

try{
List<Factura> factList = obtieneInfoService.consultaDatos(id, cvePag, fecha);
if(factList !=null && !factList.isEmpty){
 response.setExito(1);
 response.setDatos(factList);
 
 response.addHeader("Content-Type", "application/csv");
 response.addHeader("Content-Disposition", "attachment; filename=archivo.csv");
 
 PrintWriter out = response.getWriter();
			out.write("columna1,columna2,columna3");
			out.write("\n");
			
			for(Factura factu: factList){
				out.write(factu.toCSVRepresentation());
				out.write("\n");
			}
			 out.flush();
			 out.close();

}else{
  log.info("Esta vacio");
}
}catch(ControlException e){
   throw new ControlException("Error", e);
}
return response;
}

and send that error: servlet API can not call getOutputStream () after getWriter ()

What is the reason for this error? What do I need? and also, if I download the file in this same method, it will contain all the html of the page, and the information of the query

then better delete the code of the download of the file in the json method, and add another method equal to the previous one, but void, and so the file no longer contains all the html of the page, but does not collect the data of the input, leave them as null and then do nothing

This is the new method that you add, but it does not collect the data from the input, and it sends me a message that there is no data, because they are null and void, as well as repeating code, how can I do it ?, or what is it? the correct way to download the file?

@RequestMapping(value="view/obtieneArchivo")
public  void obtieneArchivo(@ResponseBody Factura fact, HttpServletRequest request, HttpServletResponse response) throws ControlException{

try{
List<Factura> factList = obtieneInfoService.consultaDatos(id, cvePag, fecha);
if(factList !=null && !factList.isEmpty){
 
 response.addHeader("Content-Type", "application/csv");
 response.addHeader("Content-Disposition", "attachment; filename=archivo.csv");
 
 PrintWriter out = response.getWriter();
			out.write("columna1,columna2,columna3");
			out.write("\n");
			
			for(Factura factu: factList){
				out.write(factu.toCSVRepresentation());
				out.write("\n");
			}
			 out.flush();
			 out.close();

}else{
  log.info("Esta vacio");
}
}catch(ControlException e){
   throw new ControlException("Error", e);
}
}

and add this function to my jsp

function descargaArchivo(){
	
	var url="${pageContext.request.contextPath}/view/obtieneArchivo";
	$.fileDownload(url)
	  .done(
	    function(){
			Helper.muestraInf("Se descargo correctamente");
		}
	  
	  )
	.fail(
		function(){
			Helper.muestraInf("Ocurrio un  error en la descarga");
		}
	);
}

I hope you can help me, I just start with this and I do not understand many things, thanks

    
asked by Root93 13.06.2018 в 06:51
source

1 answer

0

First, it is appreciated that you put the necessary information for the question -especially in comparison with other questions that are around here-. But you have passed. Only the third code fragment and the subsequent explanation are relevant. And it has nothing to do with Javascript.

On the other hand, it is usually convenient to include the stacktrace of the thrown exception and indicate the line where it is launched, if it is in your code.

Regarding the error, seeing the message, we go to the documentation of HttpServletResponse which tells us that the getWriter() method is inherited from ServletResponse . In the documentation of getWriter () tell us:

  

Either this method or getWriter () may be called to write the body, not both.

Your code does not call getOutputStream() , but it returns a structure so that the JSON API generates the response. The JSON API calls getOutputStream to write its data in response and there throws the exception.

Which is lucky, because if not, it would not have failed you but you would receive an answer that is part of your text file and JSON part.

The second attempt you make 1 does not find the variables because you simply do not send it any JSON information (there is no element data ); you can make the request simply by means of a normal and current GET request

url = '.../view/obtieneArchivo&id=' + id + '&clavePago=' + clavePago + '&fecha=' + fecha;

and in the controller obtain the values by request.getParameter() 2 .

Another option is simply to make the form have% serv_de% servlet that will generate the file.

1 Please, a question / version per question here.

2 Depending on the format, it may be necessary to encode the date with action to get a valid URL.

    
answered by 13.06.2018 в 11:13