web-dev-qa-db-fra.com

getOutputStream () a déjà été appelé pour cette réponse

Je recherche sur Google le message d'erreur getOutputStream() has already been called for this response Et beaucoup de gens disent que c'est à cause de l'espace ou d'une nouvelle ligne après le <% ou le %>, mais dans mon code, il n'y a pas d'espace ni de nouvelle ligne. J'utilise Tomcat6 sur Linux.

<%@
    page import="Java.servlet.*,
    javax.servlet.http.*,
    Java.io.*,
    Java.util.*,
    com.lowagie.text.pdf.*,
    com.lowagie.text.*"
    %><%
    response.setContentType("application/pdf");
    Document document = new Document();
    try{
        ByteArrayOutputStream buffer = new ByteArrayOutputStream();
        PdfWriter.getInstance(document, buffer);
        document.open();
        PdfPTable table = new PdfPTable(2);
        table.addCell("1");
        table.addCell("2");
        table.addCell("3");
        table.addCell("4");
        table.addCell("5");
        table.addCell("6");
        document.add(table);
        document.close();
        DataOutput dataOutput = new DataOutputStream(response.getOutputStream());
        byte[] bytes = buffer.toByteArray();
        response.setContentLength(bytes.length);
        for(int i = 0; i < bytes.length; i++)
        {
        dataOutput.writeByte(bytes[i]);
        }
    }catch(DocumentException e){
        e.printStackTrace();
    }

%>

~

org.Apache.jasper.JasperException: Java.lang.IllegalStateException: getOutputStream() has already been called for this response
    org.Apache.jasper.servlet.JspServletWrapper.handleJspException(JspServletWrapper.Java:522)
    org.Apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.Java:410)
    org.Apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.Java:342)
    org.Apache.jasper.servlet.JspServlet.service(JspServlet.Java:267)
    javax.servlet.http.HttpServlet.service(HttpServlet.Java:717)

cause première 

Java.lang.IllegalStateException: getOutputStream() has already been called for this response
    org.Apache.catalina.connector.Response.getWriter(Response.Java:610)
    org.Apache.catalina.connector.ResponseFacade.getWriter(ResponseFacade.Java:198)
    org.Apache.jasper.runtime.JspWriterImpl.initOut(JspWriterImpl.Java:125)
    org.Apache.jasper.runtime.JspWriterImpl.flushBuffer(JspWriterImpl.Java:118)
    org.Apache.jasper.runtime.PageContextImpl.release(PageContextImpl.Java:188)
    org.Apache.jasper.runtime.JspFactoryImpl.internalReleasePageContext(JspFactoryImpl.Java:118)
    org.Apache.jasper.runtime.JspFactoryImpl.releasePageContext(JspFactoryImpl.Java:77)
    org.Apache.jsp.Account.Domain.testPDF_jsp._jspService(testPDF_jsp.Java:94)
    org.Apache.jasper.runtime.HttpJspBase.service(HttpJspBase.Java:70)
    javax.servlet.http.HttpServlet.service(HttpServlet.Java:717)
    org.Apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.Java:374)
    org.Apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.Java:342)
    org.Apache.jasper.servlet.JspServlet.service(JspServlet.Java:267)
    javax.servlet.http.HttpServlet.service(HttpServlet.Java:717)
53
Southsouth

Ok, vous devriez utiliser un servlet pas un JSP mais si vous avez vraiment besoin de ... ajoutez cette directive en haut de votre page:

<%@ page trimDirectiveWhitespaces="true" %>

Ou dans la section jsp-config votre web.xml

<jsp-config>
  <jsp-property-group>
    <url-pattern>*.jsp</url-pattern>
    <trim-directive-whitespaces>true</trim-directive-whitespaces>
  </jsp-property-group>
</jsp-config>

Également flush/close la OutputStream et renvoyer une fois terminé.

dataOutput.flush();
dataOutput.close();
return;
48
RealHowTo

Le problème ici est que votre JSP parle directement à la réponse OutputStream. Techniquement, ce n'est pas interdit, mais ce n'est vraiment pas une bonne idée.

Spécifiquement, vous appelez response.getOutputStream() et écrivez des données dans cela. Plus tard, lorsque le moteur JSP essaie de vider la réponse, il échoue car votre code a déjà "réclamé" la réponse. Une application peut appeler getOutputStream ou getWriter pour n'importe quelle réponse, il n'est pas autorisé à faire les deux. Les moteurs JSP utilisent getWriter et vous ne pouvez donc pas appeler getOutputStream.

Vous devriez écrire ce code en tant que Servlet, pas en tant que JSP. Les JSP ne conviennent vraiment que pour la sortie textuelle telle que contenue dans les JSP. Vous pouvez constater qu'il n'y a pas de sortie de texte dans votre JSP, il ne contient que Java. 

35
skaffman

Ajoutez ce qui suit à la fin de try/catch pour éviter l’erreur qui apparaît lorsque le moteur JSP purge la réponse via getWriter ()

out.clear(); // where out is a JspWriter
out = pageContext.pushBody();

Comme il a été noté, ce n'est pas la meilleure pratique, mais cela évite les erreurs dans vos journaux.

9
pnairn

Je n'ai eu ce problème que la deuxième fois que je suis allé exporter. Une fois j'ai ajouté:

response.getOutputStream().flush();
response.getOutputStream().close();

une fois l'exportation terminée, mon code a commencé à fonctionner tout le temps. 

4
michaelp

Je viens de vivre ce problème. 

Le problème était dû à la tentative de ma méthode de contrôleur de retourner le type String (nom de la vue) quand il se ferme. Lorsque la méthode quitterait, un deuxième flux de réponse serait lancé. 

Changer le type de retour de la méthode du contrôleur en void a résolu le problème.

J'espère que cela aidera si quelqu'un d'autre rencontre ce problème.

3
Dan Torrey

Voici ce qui a fonctionné pour moi dans un cas similaire.

Une fois que vous avez terminé d'écrire dans la variable ServletOutputStream, appelez simplement response.sendRedirect("yourPage.jsp");. Cela provoquerait le lancement d’une nouvelle requête du navigateur, évitez donc d’écrire dans le même flux de sortie.

3
Igor

JSP est le cadre de présentation, et n’est généralement pas censé contenir de logique de programme. Comme suggéré par skaffman, utilisez des servlets pures ou n’importe quel framework Web MVC afin d’obtenir ce que vous voulez.

2
Bozho

J'ai eu la même erreur en utilisant response.getWriter() avant un request.getRequestDispatcher(path).forward(request, response);. Donc, start fonctionne bien lorsque je le remplace par response.getOutputStream()

0
Daniel De León

J'ai eu le même problème, et j'ai résolu en ajoutant simplement "retour;" à la fin du FileInputStream.

Voici mon JSP

<%@ page language="Java" contentType="text/html; charset=ISO-8859-1"
        pageEncoding="ISO-8859-1"%>
<%@ page import="Java.io.*"%>
<%@ page trimDirectiveWhitespaces="true"%>

<%

        try {
                FileInputStream ficheroInput = new FileInputStream("C:\\export_x_web.pdf");
                int tamanoInput = ficheroInput.available();
                byte[] datosPDF = new byte[tamanoInput];
                ficheroInput.read(datosPDF, 0, tamanoInput);

                response.setHeader("Content-disposition", "inline; filename=export_sise_web.pdf");
                response.setContentType("application/pdf");
                response.setContentLength(tamanoInput);
                response.getOutputStream().write(datosPDF);

                response.getOutputStream().flush();
                response.getOutputStream().close();

                ficheroInput.close();
                return;

        } catch (Exception e) {

        }
%>

</body>
</html>
0

Cette erreur se produisait dans mon programme car le jeu de résultats appelait plus de colonnes à afficher dans le document PDF que la base de données contenue. Par exemple, la table contient 30 champs mais le programme appelait 35 (resultset.getString (35))

0
Wandile Nxumalo