前端ajax+模态框,快速请求服务器获取验证码图片,怎么保证图片的快速刷新并且正常显示,不会有缓存呢?

下面我举的例子是,前端通过ajax+bootstrap的模态框,向服务器获取验证码图片。

效果:

如何实现呢?

1、第一种:

一般向服务器请求图片时,都是将图片保存在服务器上,再将网络地址URL返回,前端通过URL获取图片。

前端代码:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ include file="/resources/base/taglib.jsp"%>
<html>
<head>
    <title>Title</title>
    <script src="<c:url value='/resources/YQQ/js/jquery-3.1.0.min.js'/>"></script>
    <script src="<c:url value='/resources/YQQ/js/bootstrap.min.js'/>"></script>
    <link href="<c:url value='/resources/YQQ/css/bootstrap.min.css'/>" rel="stylesheet">
</head>
<body>

    <button class="btn btn-primary btn-lg" data-toggle="modal" data-target="#myModal" onclick="getCode()">
        获取验证码
    </button>
    <!-- 模态框(Modal) -->
    <div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
        <div class="modal-dialog">
            <div class="modal-content">
                <div class="modal-header">
                    <button type="button" class="close" data-dismiss="modal"
                            aria-hidden="true">×
                    </button>
                    <h4 class="modal-title" id="myModalLabel">
                        请输入验证码:
                    </h4>
                </div>
                <div class="modal-body">
                    <img src="" id="code">
                    <input type="text" id="codeText">
                </div>
                <div class="modal-footer">
                    <button type="button" class="btn btn-default"
                            data-dismiss="modal">关闭
                    </button>
                    <button type="button" class="btn btn-primary" onclick="mnLogin()">
                        提交
                    </button>
                </div>
            </div><!-- /.modal-content -->
        </div><!-- /.modal-dialog -->
    </div><!-- /.modal -->

</body>
<script>
    function getCode() {
        $("#code").attr("src", "");
        $.ajax({
            url: '${base}/bbm/getCode',
            type: "post",
            success: function (data) {
                setTimeout(function(){}, 500);
                $("#code").attr("src", data);
            }
        })
    }</script>
</html>

后端代码

@ResponseBody
@RequestMapping("getCode")
public String getCode(HttpServletRequest request){
    System.out.println("====");
    try {
        String imgURLPath = TestLogin.getCode(request);
        return imgURLPath;
    } catch (IOException e) {
        e.printStackTrace();
    }
    return "";
}

 

// 将验证码图片保存到服务器,并返回url访问地址
public static String getCode(HttpServletRequest request) throws IOException {
/*这一段是请求接口,获取验证码的图片*/
    HttpGet get = new HttpGet("xxxx");
    // 创建一个http客户端
    CloseableHttpClient httpClient = HttpClientBuilder.create().setDefaultCookieStore(COOKIE).build();
    // 发送get请求
    HttpResponse response = httpClient.execute(get);
    byte[] bytes = EntityUtils.toByteArray(response.getEntity());
/*这一段是请求接口,获取验证码的图片*/

    // 文件存放路径
    String realPath = request.getServletContext().getRealPath("/resources");
    // 文件名称 code.jpg
    String fileName = "code.jpg";
    // 文件输出
    File file = new File(realPath, fileName);
    FileOutputStream fileOutputStream = new FileOutputStream(file);
    fileOutputStream.write(bytes);
    fileOutputStream.close();

    String urlPath = request.getScheme() + "://" +
            request.getServerName() + ":" +
            request.getServerPort() + request.getContextPath() + "/resources/" + fileName;
    return urlPath;
}

第一种方式,存在的问题:

1)第一次访问验证码没有问题,但是关闭模态框后,再次点开发现验证码并没有发生改变,而服务器上保存的图片却改变了。

解决方法: 

只需要在请求验证码图片的url后面加入不同的参数,保证浏览器不会因为请求地址url相同,而直接从缓存中读取。

$("#code").attr("src", data + "?datetime=" + new Date().getTime() + Math.round(Math.random()*100));

2)但是修改之后,又出现新的问题:请求过快导致图片无法正常显示,并且不能够保证浏览器还是会从缓存中读取图片。

2、第二种:

因为将图片保存到服务器时,由于网络的原因有时候会慢,所以前端访问的时候,可能图片还没有保存到服务器,而导致图片无法正常显示。

解决方式:先将图片转为byte字节数组,再转为base64编码的字符串,传递给前端,前端显示显示出来即可。

为什么要使用base64编码的图片?

可以减少http请求,一个请求相当于一个网络开销。第一种方式,还需要再次发起http请求。

后端代码

@ResponseBody
@RequestMapping("getCode")
public String getCode(HttpServletRequest request){
    try {
        byte[] codeBytes = TestLogin.getCodeBytes();
        //定义一个BASE64Encoder
        BASE64Encoder encode = new BASE64Encoder();
        //将byte[]转换为base64
        String base64 = encode.encode(codeBytes);
        return base64;
    } catch (IOException e) {
        e.printStackTrace();
    }
    return null;
}

前端代码

function getCode() {
    $("#code").attr("src", "");
    $.ajax({
        url: '${base}/bbm/getCode',
        type: "post",
        success: function (data) {
            if (data!=null){
                str = 'data:image/png;base64,' + data;
                $("#code").attr("src", str);
            }else{
                alert("错误");
            }
        }
    })
}

 这样的话,无论关闭模态框 / 显示模态框,点击多快,都不会出现验证码图片显示不正常的请求,也保证每次的验证码都是不同的。

 

posted @ 2020-07-13 11:32  忘忧山的兰木  阅读(648)  评论(0编辑  收藏  举报
她只是想吃这个而已啊……这一定是她非常爱吃的,我居然连如此细微的幸福也夺走了……
Hide
Switch
Save