加上response.reset(),并且所有的%>后面不要换行,包括最后一个; 因为Application Server在处理编译jsp时对于%>和<%之间的内容一般是原样输出,而且默认是PrintWriter, 而你却要进行流输出:ServletOutputStream,这样做相当于试图在Servlet中使用两种输出机制, 就会发生:getOutputStream() has already been called for this response的错误 详细请见《More Java Pitfill》一书的第二部分 Web层Item 33:试图在Servlet中使用两种输出机制 270 而且如果有换行,对于文本文件没有什么问题,但是对于其它格式,比如AutoCAD、Word、Excel等文件 下载下来的文件中就会多出一些换行符0x0d和0x0a,这样可能导致某些格式的文件无法打开,有些也可以正常打开
String vcode = sn2vcode(); arg0.getSession().setAttribute("rand",vcode) ;//代码内容写入session中 if (svgMode) outSVG(vcode, arg1); else outJPEG(vcode, arg1); } private void outSVG(String vcode, HttpServletResponse resp) throws IOException { resp.setContentType("image/svg+xml"); resp.getOutputStream().print(SVG_SOURCE1 + vcode + SVG_SOURCE2); } private void outJPEG(String vcode, HttpServletResponse resp) throws IOException { resp.setContentType("image/jpeg"); BufferedImage image = new BufferedImage(IMAGE_WIDTH, IMAGE_HEIGHT, BufferedImage.TYPE_INT_RGB); Random random = new Random(); Graphics g = image.getGraphics(); //g.setColor(getRandColor(200, 250)); g.fillRect(0, 0, IMAGE_WIDTH, IMAGE_HEIGHT); g.setFont(new Font("Times New Roman", Font.PLAIN, 18)); //g.setColor(getRandColor(160, 200)); for (int i = 0; i < 155; i++) { int x = random.nextInt(IMAGE_WIDTH); int y = random.nextInt(IMAGE_HEIGHT); int xl = random.nextInt(12); int yl = random.nextInt(12); g.drawLine(x, y, x + xl, y + yl); } for (int i = 1; i <= 4; i++) { String rand = vcode.substring(i - 1, i); g.setColor(new Color(20 + random.nextInt(110), 20 + random.nextInt(110), 20 + random.nextInt(110))); g.drawString(rand, 13 * (i - 1) + 0, 16); } ImageWriter writer = (ImageWriter) ImageIO.getImageWritersByFormatName("jpeg").next(); JPEGImageWriteParam params = new JPEGImageWriteParam(null); ImageOutputStream ios = ImageIO.createImageOutputStream(resp.getOutputStream()); writer.setOutput(ios); writer.write(null, new IIOImage(image, null, null), params); writer.dispose(); ios.close(); } static String sn2vcode() { String sRand = ""; Random random = new Random(); for (int i=0;i<4;i++) { String rand=String.valueOf(random.nextInt(10)); sRand+=rand; } return sRand; } public void init() throws ServletException { try { GraphicsEnvironment.getLocalGraphicsEnvironment(); } catch (Throwable e) {
svgMode = true; } } public Color getRandColor(int fc, int bc) { Random random = new Random(); if (fc > 255) fc = 255; if (bc > 255) bc = 255; int r = fc + random.nextInt(bc - fc); int g = fc + random.nextInt(bc - fc); int b = fc + random.nextInt(bc - fc); return new Color(r, g, b); } }
在页面中直接写: <body bgcolor="#ffffff"> <h1> <% response.getOutputStream(); %> </h1> </body> 就会出错,应该输出流只能被打开一次,而生成servlet以后,在你的语句之前已经被打开过了。 因为servlet要输出html标签。 这是jdk中的说明: java.lang.IllegalStateException - if the getWriter method has been called on this response getWriter method,看清楚,不一定是getOutputStream
因为Application Server在处理编译jsp时对于%>和<%之间的内容一般是原样输出,而且默认是PrintWriter,
而你却要进行流输出:ServletOutputStream,这样做相当于试图在Servlet中使用两种输出机制,
就会发生:getOutputStream() has already been called for this response的错误
详细请见《More Java Pitfill》一书的第二部分 Web层Item 33:试图在Servlet中使用两种输出机制 270
而且如果有换行,对于文本文件没有什么问题,但是对于其它格式,比如AutoCAD、Word、Excel等文件
下载下来的文件中就会多出一些换行符0x0d和0x0a,这样可能导致某些格式的文件无法打开,有些也可以正常打开
import java.io.*;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.GraphicsEnvironment;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;
import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageWriter;
import javax.imageio.plugins.jpeg.JPEGImageWriteParam;
import javax.imageio.stream.ImageOutputStream;
import javax.servlet.*;
import javax.servlet.http.*;
public class VerifyCodeServlet extends HttpServlet
{
private static final int IMAGE_WIDTH = 60;
private static final int IMAGE_HEIGHT = 20;
private static final int FONT_HEIGHT = 16;
private static final String SVG_SOURCE1 = "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.0//EN\" \"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd\">"
+ "<svg width=\""
+ IMAGE_WIDTH
+ "\" height=\""
+ IMAGE_HEIGHT
+ "\" xmlns=\"http://www.w3.org/2000/svg\">"
+ "<text x=\"0\" y=\""
+ IMAGE_HEIGHT
+ "\" font-family=\"Arial\" font-size=\""
+ IMAGE_HEIGHT + "\" fill=\"black\">"; private static final String SVG_SOURCE2 = "</text></svg>";
private boolean svgMode = false;
private PrintWriter out = null;
protected void service(HttpServletRequest arg0, HttpServletResponse arg1) throws ServletException, IOException
{
//if (sn == null)
// return;
String vcode = sn2vcode(); arg0.getSession().setAttribute("rand",vcode) ;//代码内容写入session中 if (svgMode)
outSVG(vcode, arg1);
else
outJPEG(vcode, arg1);
}
private void outSVG(String vcode, HttpServletResponse resp) throws IOException
{
resp.setContentType("image/svg+xml");
resp.getOutputStream().print(SVG_SOURCE1 + vcode + SVG_SOURCE2);
} private void outJPEG(String vcode, HttpServletResponse resp) throws IOException
{
resp.setContentType("image/jpeg");
BufferedImage image = new BufferedImage(IMAGE_WIDTH, IMAGE_HEIGHT,
BufferedImage.TYPE_INT_RGB);
Random random = new Random();
Graphics g = image.getGraphics();
//g.setColor(getRandColor(200, 250));
g.fillRect(0, 0, IMAGE_WIDTH, IMAGE_HEIGHT);
g.setFont(new Font("Times New Roman", Font.PLAIN, 18));
//g.setColor(getRandColor(160, 200));
for (int i = 0; i < 155; i++)
{
int x = random.nextInt(IMAGE_WIDTH);
int y = random.nextInt(IMAGE_HEIGHT);
int xl = random.nextInt(12);
int yl = random.nextInt(12);
g.drawLine(x, y, x + xl, y + yl);
}
for (int i = 1; i <= 4; i++)
{
String rand = vcode.substring(i - 1, i);
g.setColor(new Color(20 + random.nextInt(110), 20 + random.nextInt(110), 20 + random.nextInt(110)));
g.drawString(rand, 13 * (i - 1) + 0, 16);
}
ImageWriter writer = (ImageWriter) ImageIO.getImageWritersByFormatName("jpeg").next();
JPEGImageWriteParam params = new JPEGImageWriteParam(null);
ImageOutputStream ios = ImageIO.createImageOutputStream(resp.getOutputStream());
writer.setOutput(ios);
writer.write(null, new IIOImage(image, null, null), params);
writer.dispose();
ios.close();
} static String sn2vcode()
{
String sRand = "";
Random random = new Random();
for (int i=0;i<4;i++)
{
String rand=String.valueOf(random.nextInt(10));
sRand+=rand;
}
return sRand;
}
public void init() throws ServletException
{
try
{
GraphicsEnvironment.getLocalGraphicsEnvironment();
}
catch (Throwable e)
{
svgMode = true;
}
}
public Color getRandColor(int fc, int bc)
{ Random random = new Random();
if (fc > 255)
fc = 255;
if (bc > 255)
bc = 255;
int r = fc + random.nextInt(bc - fc);
int g = fc + random.nextInt(bc - fc);
int b = fc + random.nextInt(bc - fc);
return new Color(r, g, b);
}
}
<body bgcolor="#ffffff">
<h1>
<%
response.getOutputStream();
%>
</h1>
</body>
就会出错,应该输出流只能被打开一次,而生成servlet以后,在你的语句之前已经被打开过了。
因为servlet要输出html标签。
这是jdk中的说明:
java.lang.IllegalStateException - if the getWriter method has been called on this response
getWriter method,看清楚,不一定是getOutputStream