前端ajax+模態框,快速請求伺服器獲取驗證碼圖片,怎麼保證圖片的快速重新整理並且正常顯示,不會有快取呢?
阿新 • • 發佈:2020-07-13
下面我舉的例子是,前端通過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("錯誤"); } } }) }
這樣的話,無論關閉模態框 / 顯示模態框,點選多快,都不會出現驗證碼圖片顯示不正常的請求,也保證每次的驗證碼都是不同的。