案例一:发送验证码案例
1、 定义一个 Servlet 用来在内存中生成 二维码图片,并向浏览器页面输出。
1 import javax.imageio.ImageIO;
2 import javax.servlet.ServletException;
3 import javax.servlet.annotation.WebServlet;
4 import javax.servlet.http.HttpServlet;
5 import javax.servlet.http.HttpServletRequest;
6 import javax.servlet.http.HttpServletResponse;
7 import java.awt.*;
8 import java.awt.image.BufferedImage;
9 import java.io.IOException;
10 import java.util.Random;
11
12 @WebServlet("/checkCodeServlet")
13 public class CheckCodeServlet extends HttpServlet {
14 protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
15
16 // 定义图片的宽高
17 int width = 100;
18 int height = 50;
19
20 // 1 创建对象,在内存中生成图片(验证码图片对象)
21 BufferedImage image = new BufferedImage(width,height,BufferedImage.TYPE_INT_BGR);
22
23 // 2 修饰图片
24 // 2.1 填充背景色
25 Graphics g = image.getGraphics(); //获取画笔对象
26 g.setColor(Color.pink); // 设置画笔颜色
27 g.fillRect(0,0,width,height); // 绘制一个矩形,给定坐标与宽高
28
29 // 2.2 画边框
30 g.setColor(Color.blue); // 设置画笔颜色
31 g.drawRect(0,0,width-1,height-1); // 给图像绘制边框
32
33 String str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghigklmnopqrstuvwxyz0123456789";
34 //生成随机角标
35 Random ran = new Random();
36
37 for (int i = 1; i <= 4; i++) {
38 int index = ran.nextInt(str.length());
39 //获取字符
40 char ch = str.charAt(index);//随机字符
41 //2.3写验证码
42 g.drawString(ch+"",width/5*i,height/2);
43 }
44
45 //2.4画干扰线
46 g.setColor(Color.GREEN);
47
48 // 随机生成坐标点
49
50 for (int i = 0; i < 6; i++) {
51 int x1 = ran.nextInt(width);
52 int x2 = ran.nextInt(width);
53
54 int y1 = ran.nextInt(height);
55 int y2 = ran.nextInt(height);
56 g.drawLine(x1,y1,x2,y2); // 画干扰线
57 }
58
59
60 // 3 将图片输出到页面展示:通过response 的 字符流,将图片输出到浏览器上
61 ImageIO.write(image,"jpg",response.getOutputStream());
62 }
63
64 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
65 this.doPost(request, response);
66 }
67 }
2、 定义一个web页面,用来查看验证码,可以刷新验证码。
1 <!DOCTYPE html>
2 <html lang="en">
3 <head>
4 <meta charset="UTF-8">
5 <title>验证码</title>
6
7 <script>
8 /*
9 点击超链接或者图片,需要换一张
10 1.给超链接和图片绑定单击事件
11
12 2.重新设置图片的src属性值
13
14 */
15 window.onload = function(){
16 //1.获取图片对象
17 var img = document.getElementById("checkCode");
18 //2.绑定单击事件
19 img.onclick = function(){
20 //加时间戳
21 var date = new Date().getTime();
22
23 img.src = "/web/checkCodeServlet?"+date;
24 }
25
26 // 获取超链接对象
27 var a = document.getElementById("change");
28
29 a.onclick = img.onclick();
30
31 }
32
33
34 </script>
35
36
37 </head>
38 <body>
39
40
41 <img id="checkCode" src="/web/checkCodeServlet" />
42
43 <a id="change" href="javascript:;">看不清换一张?</a>
44
45 </body>
46 </html>
3、 效果图
案例二: 文件下载案例
1、文件下载需求:
1. 页面显示超链接
2. 点击超链接后弹出下载提示框
3. 完成图片文件下载
2、分析过程:
1. 超链接指向的资源如果能够被浏览器解析,则在浏览器中展示,如果不能解析,则弹出下载提示框。不满足需求
2. 任何资源都必须弹出下载提示框
3. 使用响应头设置资源的打开方式: content-disposition:attachment;filename=xxx
3、步骤:
1. 定义页面,编辑超链接href属性,指向Servlet,传递资源名称filename
2. 定义Servlet
1. 获取文件名称
2. 使用字节输入流加载文件进内存
3. 指定response的响应头: content-disposition:attachment;filename=xxx
4. 将数据写出到response输出流
4、下载页面:
1 <!DOCTYPE html>
2 <html lang="en">
3 <head>
4 <meta charset="UTF-8">
5 <title>文件下载</title>
6 </head>
7 <body>
8
9
10 <a href="/day13/img/狐狸.jpg">图片1</a>
11
12 <a href="/day13/img/2.jpg">图片2</a>
13
14 <a href="/day13/img/1.avi">视频</a>
15 <hr>
16
17
18 <a href="/day13/downloadservlet?filename=狐狸.jpg">图片1</a>
19
20 <a href="/day13/downloadservlet?filename=2.jpg">图片2</a>
21
22 <a href="/day13/downloadservlet?filename=1.avi">视频</a>
23
24
25
26
27 </body>
28 </html>
5、DownLoadServlet 类
1 import javax.servlet.ServletContext;
2 import javax.servlet.ServletException;
3 import javax.servlet.ServletOutputStream;
4 import javax.servlet.annotation.WebServlet;
5 import javax.servlet.http.HttpServlet;
6 import javax.servlet.http.HttpServletRequest;
7 import javax.servlet.http.HttpServletResponse;
8 import java.io.FileInputStream;
9 import java.io.IOException;
10
11 @WebServlet("/downloadservlet")
12 public class downloadservlet extends HttpServlet {
13 protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
14 //1获取请求参数,文件名称
15 String filename = request.getParameter("filename");
16
17 //2使用字节输入流加载文件进内存
18 // 2.1 找文件服务器路径
19 ServletContext servletContext = this.getServletContext();
20 String realPath = servletContext.getRealPath("/img/" + filename);
21
22 //2.2 使用字节流关联
23 FileInputStream fis = new FileInputStream(realPath);
24
25 //3 设置 response 的响应头
26 // 3.1 设置响应头类型:content-type
27 String mimeType = servletContext.getMimeType(filename);
28 response.setHeader("content-type",mimeType);
29 // 3.2 设置响应头打开方式:content-disposition
30
31 response.setHeader("content-disposition","attachment;filename="+filename);
32
33
34 // 4. 将输入流的数据写出到输出流中
35 ServletOutputStream sos = response.getOutputStream();
36
37 byte[] buff = new byte[1024*8];
38 int len = 0;
39
40 while((len = fis.read(buff)) != -1) {
41 sos.write(buff,0,buff.length);
42 }
43
44 // 关闭流对象
45 fis.close();
46 }
47
48 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
49 this.doPost(request, response);
50 }
51 }
上面的案例中发现,当下载的文件名字是中文的时候,下载的时候会出现乱码。
6、文件名中文乱码问题
解决思路:
(1)获取客户端使用的浏览器版本信息
(2)根据不同的版本信息,设置 filename 的编码方式不同
编码工具类:
使用 Base64 编码,需要导入 commons-codec-1.13.jar 包。
1 package cn.itcast.download;
2
3
4 import org.apache.commons.codec.binary.Base64;
5
6 import java.io.UnsupportedEncodingException;
7 import java.net.URLEncoder;
8
9
10 public class DownLoadUtils {
11
12 public static String getFileName(String agent, String filename) throws UnsupportedEncodingException {
13 if (agent.contains("MSIE")) {
14 // IE浏览器
15 filename = URLEncoder.encode(filename, "utf-8");
16 filename = filename.replace("+", " ");
17 } else if (agent.contains("Firefox")) {
18 Base64 base64Encoder = new Base64();
19 // 火狐浏览器
20 //BASE64Encoder base64Encoder = new BASE64Encoder();
21 filename = "=?utf-8?B?" + base64Encoder.encode(filename.getBytes("utf-8")) + "?=";
22 } else {
23 // 其它浏览器
24 filename = URLEncoder.encode(filename, "utf-8");
25 }
26 return filename;
27 }
28 }
7、DownLoadServlet 类(改进):
1 package cn.itcast.download;
2
3 import javax.servlet.ServletContext;
4 import javax.servlet.ServletException;
5 import javax.servlet.ServletOutputStream;
6 import javax.servlet.annotation.WebServlet;
7 import javax.servlet.http.HttpServlet;
8 import javax.servlet.http.HttpServletRequest;
9 import javax.servlet.http.HttpServletResponse;
10 import java.io.FileInputStream;
11 import java.io.IOException;
12
13 @WebServlet("/downloadservlet")
14 public class downloadservlet extends HttpServlet {
15 protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
16 //1获取请求参数,文件名称
17 String filename = request.getParameter("filename");
18
19 //2使用字节输入流加载文件进内存
20 // 2.1 找文件服务器路径
21 ServletContext servletContext = this.getServletContext();
22 String realPath = servletContext.getRealPath("/img/" + filename);
23
24 //2.2 使用字节流关联
25 FileInputStream fis = new FileInputStream(realPath);
26
27 //3 设置 response 的响应头
28 // 3.1 设置响应头类型:content-type
29 String mimeType = servletContext.getMimeType(filename);
30 response.setHeader("content-type",mimeType);
31 // 3.2 设置响应头打开方式:content-disposition
32
33 // 3.3 解决中文文件名问题
34 // 1 获取 user-agent 请求头
35 String agent = request.getHeader("user-agent");
36 // 2 使用工具类方法编码文件即可
37 filename = DownLoadUtils.getFileName(agent, filename);
38
39 response.setHeader("content-disposition","attachment;filename="+filename);
40
41
42 // 4. 将输入流的数据写出到输出流中
43 ServletOutputStream sos = response.getOutputStream();
44
45 byte[] buff = new byte[1024*8];
46 int len = 0;
47
48 while((len = fis.read(buff)) != -1) {
49 sos.write(buff,0,buff.length);
50 }
51
52 // 关闭流对象
53 fis.close();
54 }
55
56 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
57 this.doPost(request, response);
58 }
59 }