异常:getOutputStream() has already been called for this response

来源:互联网 发布:搜一次CMS 编辑:程序博客网 时间:2024/06/01 10:32


应用中有上传图片的功能, 如果将图片上传到应用目录下, 那么在显示的时候, 只需要拼接字符串, 比较简单, 但是图像不好管理。


如果将图片存放到应用外面, 那么, 在显示的时候, 拼接图片地址肯定是不行的。


需要通过流的方式读取图片, 假如我把图片存放在应用所在服务器c 盘的uploadPic目录下:


try {OutputStream outStream = response.getOutputStream();// 得到向客户端输出二进制数据的对象FileInputStream fis = new FileInputStream("c:/uploadPic/test.jpg"); // 以byte流的方式打开文件// 读数据byte data[] = new byte[1000];while (fis.read(data) > 0) {outStream.write(data);}fis.close();response.setContentType("image/*"); // 设置返回的文件类型outStream.write(data); // 输出数据outStream.flush();
outStream.close();
} catch (IOException e) {e.printStackTrace();}

如果是servlet, 那么只需将页面img的标签的src设置为该servlet的访问路径即可。

不过, 今天我用的是struts, 在错做时出现了问题, 

图片可以正常显示, 但是后台报异常:

getOutputStream() has already been called for this response

逻辑是:根据一个id查到一个图片的路径, 然后显示到页面上:
package com.ra.struts.action;import java.io.FileInputStream;import java.io.IOException;import java.io.OutputStream;import java.util.Map;import javax.servlet.ServletOutputStream;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import org.apache.struts.action.Action;import org.apache.struts.action.ActionForm;import org.apache.struts.action.ActionForward;import org.apache.struts.action.ActionMapping;import com.ra.service.CustomerException;import com.ra.service.CustomerManagerService;import com.ra.service.GoBidCenterService;public class ShowImageAction extends Action {private GoBidCenterService goBidCenterService;public GoBidCenterService getGoBidCenterService() {return goBidCenterService;}public void setGoBidCenterService(GoBidCenterService goBidCenterService) {this.goBidCenterService = goBidCenterService;}public ActionForward execute(ActionMapping mapping, ActionForm form,HttpServletRequest request, HttpServletResponse response) {try {String id=request.getParameter("id");Map<String, String> bidInfo=goBidCenterService.getBidInfo(Long.parseLong(id));OutputStream outStream = response.getOutputStream();// 得到向客户端输出二进制数据的对象FileInputStream fis = new FileInputStream("c:/uploadPic/"+bidInfo.get("image")); // 以byte流的方式打开文件// 读数据byte data[] = new byte[1000];while (fis.read(data) > 0) {outStream.write(data);}fis.close();response.setContentType("image/*"); // 设置返回的文件类型outStream.write(data); // 输出数据outStream.flush();outStream.close();} catch (IOException e) {e.printStackTrace();}return mapping.findForward("BidCenter");}}



结果问题出在
return mapping.findForward("BidCenter");
删掉之后, 程序正常。
为什么呢?


一个jsp页面在首次访问时, 会被编译为一个servlet, 当访问这个jsp时, 生成该servlet, 然后当文档解析到src时, 发现是个servlet(或者action, 一个道理), 然后

去读这个地址, 读完后, 图片被加载进来, 然后根据返回值, 要跳转, 所以, 会把要跳转到的那个页面加载到该jsp页面, 于是报错。因为两个jsp生成的servlet中都有


getOutputStream 方法。


个人看法, 欢迎指正。





在J2EE的API参考里有这么个:

ServletResponse的getWriter()方法里会抛出这个异常,

IllegalStateException - if the getOutputStream method has already been called
for this response object

而它的getOutputStream()方法里会抛出这个异常.

IllegalStateException - if the getOutputStream method has already been called for this response object

并且两者的函数申明里都有这么样的一句
Either this method or getOutputStream() may be called to write the body, not both.
Either this method or getWriter() may be called to write the body, not both.



在页面中直接写:
<body bgcolor="#ffffff">
<h1>
<%
response.getOutputStream();
%>
</h1>
</body>
将会出现错误消息如下:
java.lang.IllegalStateException: getOutputStream() has already been called for this response
org.apache.catalina.connector.Response.getWriter(Response.java:604)
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)


参考文档:http://blog.csdn.net/iron_wang/article/details/4204672