学习Response的一些小案例
利用IO流实现文件的下载
字节流的意义在于下载文件
磁盘与内存之间的IO流
浏览器与服务器之间的IO流
下面,我们用字节流实现文件的下载
Servlet类
//通过浏览器点击进行下载
@WebServlet("/down")
public class FileDownloadServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String filename = request.getParameter("filename");
//处理后的文件名
String saveName = getFileName(request,filename);
//自动根据文件的后缀名得到mime-type类型 .jpg image/jpeg,如果不根据文件名自动变化的话,那么每次都需要指定其类型
String mimeType = getServletContext().getMimeType(filename);
//指令,调用浏览器弹出下载框,由用户自己保存
response.setHeader("Content-Type", mimeType);
response.setHeader("Content-Disposition", "attachment;filename="+saveName);
//由于文件在src目录下,通过类加载器来加载文件
InputStream inputStream = getServletContext().getResourceAsStream("download/"+filename);
//将信息返回给浏览器
OutputStream outputStream = response.getOutputStream();
//在service文件夹下创建一个新的service类来处理
FileDwonloadService fileDwonloadService = new FileDwonloadService();
//调用其下的方法,并将输入输出流对象传递进去
fileDwonloadService.dwonload(inputStream,outputStream);
//使用完后,要关闭流,最后开启的先关闭
outputStream.close();
inputStream.close();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request,response);
}
/**
* 用于解决,文件名中存在中文的问题
* @param request
* @param filename
* @return 更改编码之后的文件名
* @throws UnsupportedEncodingException
*/
public String getFileName(HttpServletRequest request,String filename) throws UnsupportedEncodingException {
String agent = request.getHeader("User-Agent");
if (agent.contains("MSIE")) {
// IE浏览器
filename = URLEncoder.encode(filename, "utf-8");
filename = filename.replace("+", " ");
} else if (agent.contains("Firefox")) {
// 火狐浏览器
BASE64Encoder base64Encoder = new BASE64Encoder();
filename = "=?utf-8?B?" + base64Encoder.encode(filename.getBytes("utf-8")) + "?=";
} else {
// 其它浏览器
filename = URLEncoder.encode(filename, "utf-8");
}
return filename;
}
}
service类
public class FileDwonloadService {
public void dwonload(InputStream inputStream, OutputStream outputStream) throws IOException {
//进行边读边写文件
//定义一个缓冲空间
byte[] bytes = new byte[1024];
int len = 0;
//将文件读取出来后,写入
while ((len = inputStream.read(bytes)) != -1){
outputStream.write(bytes,0,len);
}
}
}
但是由于没有加上前端页面,所以每次下载时,需要自己在地址上加上?filename=文件名(需要加上后缀名)
浏览器访问Servlet显示图片
如果浏览器访问Servlet,Servlet响应的是图片时,则不能使用response.getWriter().write(),需要使用ImageIO.write(BufferedImage im,String formatName,OutputStream output);,才能显示出图片。
其中
ImageIO.write(BufferedImage im,String formatName,OutputStream output)中的参数分别代表:
第一个参数:可访问图像数据缓冲区的 Image
第二个参数:图片的类型
第三个参数:字节输出流
@WebServlet("/code")
public class VerificationCodeServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//创建生成验证码的类
VerificationCodeService verificationCode = new VerificationCodeService();
//调用生成验证码的方法
String code = verificationCode.create();
//输出打印code
System.out.println(code);
//将生成的验证码转化为图片
BufferedImage image = verificationCode.changeStringToImage(code);
// response.getWriter().println(image);//是图片的话,就不能这样写了
ImageIO.write(image,"jpeg",response.getOutputStream());//参1,内存中的图片 参2,格式 参3,字节输出流
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request,response);
}
}
使用Servlet实现验证码
开发步骤:
- 获得含有4个字符的字符串
- 将字符串转换成图片
- 将图片显示在浏览器
HTML页面
<body>
<form method="post" action="">
账号:<input type="text" name="username"><br/>
密码:<input type="password" name="password"><br/>
验证码:<input type="text" name="code"/><img id="img" src="/webDay03_war_exploded/code"></img><br/>
<input type="submit" value="提交">
</form>
</body>
<script type="application/javascript">
const img = document.getElementById("img");
//给img标签添加点击事件,就可以点击图片,就刷新
img.onclick = function(){
img.src = "/webDay03_war_exploded/code?time="+new Date();
}
</script>
servlet代码
@WebServlet("/code")
public class VerificationCodeServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//创建生成验证码的类
VerificationCodeService verificationCode = new VerificationCodeService();
//调用生成验证码的方法
String code = verificationCode.create();
//输出打印code
System.out.println(code);
//将生成的验证码转化为图片
BufferedImage image = verificationCode.changeStringToImage(code);
// response.getWriter().println(image);//是图片的话,就不能这样写了
ImageIO.write(image,"jpeg",response.getOutputStream());//参1,内存中的图片 参2,格式 参3,字节输出流
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request,response);
}
}
service代码
public class VerificationCodeService {
//生成验证码
public String create() {
//创建验证码字符
String code = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
//创建Random对象,用来创建随机字符
Random random = new Random();
//新建一个StringBuilder对象,用来存放字符
StringBuilder builder = new StringBuilder();
//获得4字符的验证码
for (int i = 0; i < 4; i++) {
int index = random.nextInt(code.length());
char newChar = code.charAt(index);
builder.append(newChar);
}
return builder.toString();
}
//字符串转图片
public BufferedImage changeStringToImage(String code) {
Random rd = new Random();
//创建一个画布
BufferedImage image = new BufferedImage(75, 28, BufferedImage.TYPE_INT_RGB);
//画笔
Graphics g = image.getGraphics();
//给画笔设置颜色
g.setColor(new Color(240,240,240)); //#00000 FFFFFF
//设置验证码的 背景色
g.fillRect(0, 0, 75, 28);
g.setFont(new Font("宋体",Font.BOLD,16));
g.setColor(new Color(0,0,0)); //#00000 FFFFFF
// g.drawString(checkCodeStr, 20, 20);
for (int i = 0; i <4 ; i++) {
//画字符
g.setColor(new Color(rd.nextInt(120),rd.nextInt(120),rd.nextInt(120)));
g.drawString(code.charAt(i)+"", 16*i + rd.nextInt(16), 15 + rd.nextInt(10) );
if(i % 2 == 0) {//画线
g.setColor(new Color(rd.nextInt(120), rd.nextInt(120), rd.nextInt(120)));
g.drawLine(rd.nextInt(75), rd.nextInt(28), rd.nextInt(75), rd.nextInt(28));
}
}
return image;
}
}
最后实现的页面为