利用IO流实现文件的下载,浏览器访问Servlet显示图片,使用Servlet实现验证码

学习Response的一些小案例

利用IO流实现文件的下载

字节流的意义在于下载文件

磁盘与内存之间的IO流
img

浏览器与服务器之间的IO流
img

下面,我们用字节流实现文件的下载
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;
    }

}

最后实现的页面为
验证码

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值