エラーメッセージgetOutputStream() has already been called for this response
をグーグルで検索し、多くの人が<%
または%>
の後のスペースまたは改行のためだと言いましたが、私のコードではスペースも改行もありません。 LinuxでTomcat6を使用しています。
<%@
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)
根本的な原因
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)
OK、JSPではなくservletを使用する必要がありますが、本当に必要な場合は、このディレクティブをページの上部に追加します。
<%@ page trimDirectiveWhitespaces="true" %>
または、jsp-configセクションでweb.xml
<jsp-config>
<jsp-property-group>
<url-pattern>*.jsp</url-pattern>
<trim-directive-whitespaces>true</trim-directive-whitespaces>
</jsp-property-group>
</jsp-config>
flush
/close
the OutputStream
も完了し、完了したら戻ります。
dataOutput.flush();
dataOutput.close();
return;
ここでの問題は、JSPが応答OutputStream
と直接通信していることです。これは技術的に禁じられているわけではありませんが、あまり良い考えではありません。
具体的には、response.getOutputStream()
を呼び出し、それにデータを書き込みます。後で、JSPエンジンが応答をフラッシュしようとすると、コードが既に応答を「要求」しているため失敗します。アプリケーションは、任意の応答でgetOutputStream
またはgetWriter
を呼び出すことができますが、両方を行うことはできません。 JSPエンジンはgetWriter
を使用するため、getOutputStream
を呼び出すことはできません。
このコードは、JSPではなくサーブレットとして作成する必要があります。 JSPは、JSPに含まれているテキスト出力にのみ本当に適しています。 JSPには実際のテキスト出力はなく、Javaのみが含まれていることがわかります。
JSPエンジンがgetWriter()を介して応答をフラッシュするときに表示されるエラーを回避するために、try/catchの末尾に次を追加します。
out.clear(); // where out is a JspWriter
out = pageContext.pushBody();
既に述べたように、これはベストプラクティスではありませんが、ログのエラーを回避します。
この問題は、エクスポートに2回目に行ったときにのみ発生しました。追加したら:
response.getOutputStream().flush();
response.getOutputStream().close();
エクスポートが完了した後、私のコードは常に機能し始めました。
この問題が発生しました。
この問題は、コントローラーメソッドが終了時にString(view name)の戻り値のタイプを試みたために発生しました。メソッドが終了すると、2番目の応答ストリームが開始されます。
コントローラーメソッドの戻り値の型をvoidに変更すると、問題は解決しました。
他の誰かがこの問題を経験した場合にこれが役立つことを願っています。
同様のケースで私にとってうまくいったのは次のとおりです。
Servlet
OutputStream
への書き込みが完了したら、response.sendRedirect("yourPage.jsp");
を呼び出します。これにより、ブラウザからの新しいリクエストが開始されるため、同じ出力ストリームへの書き込みは避けてください。
JSPはプレゼンテーションフレームワークであり、通常、プログラムロジックを含むことは想定されていません。スカッフマンが示唆したように、純粋なサーブレットまたは任意のMVC Webフレームワークを使用して、目的を達成します。
response.getWriter()
の前にrequest.getRequestDispatcher(path).forward(request, response);
を使用すると、同じエラーが発生しました。したがって、response.getOutputStream()
に置き換えると、startは正常に機能します。
同じ問題が発生し、「リターン」を追加するだけで解決しました。 FileInputStreamの最後。
ここに私の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>
このエラーは、結果セットがPDF Documentに含まれるデータベースよりも多くの列を呼び出しているため、プログラムで発生していました。たとえば、テーブルには30のフィールドが含まれていますが、プログラムは35を呼び出していました(resultset.getString(35))