調用http接口並實現圖片傳遞的關鍵分爲兩部分javascript
其一:建立servlet接口,加圖片上傳註解,用於接收傳過來的圖片等信息,並作進一步的處理後,返回json格式的結果html
其二:建立htpclient,而且運用MultipartEntity對圖片進行封裝,調用http接口,獲取返回值,進行下一步處理java
下面就以人臉識別登陸,來說解帶有圖片的http接口的調用過程jquery
一、建立jsp頁面,用於獲取到人臉信息web
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html lang="ZH-CN"> <head> <meta charset="utf-8"> <title>人臉識別登陸</title> <style> .booth { width:340px; background:#ccc; border: 10px solid #ddd; margin: 0 auto; } .btn input[type=button] { width: 60px; height: 30px; line-height: 30px; margin: 3px; } </style> <script type="text/javascript" src="js/jquery.js"></script> </head> <body> <div class="booth"> <input type="button" value="登陸" onclick="doLogin('login');"> <video id="video" width="320" height="240"></video> <canvas id='canvas' style="display:none;"></canvas> </div> <script type="text/javascript"> var video = document.getElementById('video'), canvas = document.getElementById('canvas'), vendorUrl = window.URL || window.webkitURL; //媒體對象 navigator.getMedia = navigator.getUserMedia || navagator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia; navigator.getMedia({ video: true, //使用攝像頭對象 audio: false //不適用音頻 }, function(strem){ console.log(strem); video.src = vendorUrl.createObjectURL(strem); video.play(); }, function(error) { //error.code console.log(error); }); function doLogin(method) { //繪製canvas圖形 canvas.getContext('2d').drawImage(video, 0, 0, 320, 240); //把canvas圖像轉爲img圖片 $.ajax({ url : 'login.do?method='+method, type : "POST", dataType : 'json', async : false, data : {image : canvas.toDataURL("image/png")}, success : function(data) { alert(data.flag+'---'+data.message); var msg = data.message; if (msg != "success") { resultflag=false; } }, error : function(error) { tip('訪問數據異常', '異常提示'); return true; } }); } </script> </body> </html>
二、在loginController中編寫建立httpclient的方法,並調用接口、ajax
/** * 調用接口,實現人臉識別登陸 * @param req * @param resp * @param model * @throws IOException */ @RequestMapping(value = "login_ai.do", method = RequestMethod.POST) public void login_ai(HttpServletRequest req, HttpServletResponse resp, ModelMap model) { try { resp.setContentType("application/text; charset=utf-8"); String basePath = "upload/"; String filePath = req.getSession().getServletContext() .getRealPath("/") + basePath; String fileName = getDate("yyyyMMddHHmmss") + ".png"; // 默認傳入的參數帶類型等參數:data:image/png;base64, PrintWriter out = resp.getWriter(); com.alibaba.fastjson.JSONObject loginInfo = new com.alibaba.fastjson.JSONObject(); String imgStr = req.getParameter("image"); if (null != imgStr) { imgStr = imgStr.substring(imgStr.indexOf(",") + 1); } // 每次上傳文件以前,須要先將以前的文件刪除掉 File file = new File(filePath); if (file.isDirectory()) { for (File f : file.listFiles()) { f.delete(); } } // 文件上傳到服務器 Boolean flag = ImageCompressUtil.GenerateImage(imgStr, filePath, fileName); String newfileName = fileName.substring(0, fileName.indexOf(".")) + "_bak" + fileName.substring(fileName.indexOf(".")); // loginInfo = HttpUtil.sendPostWithImage(AIConstant.LOGIN_REGIST_URL // + "?method=login", filePath+newfileName); HttpClient client = new DefaultHttpClient(); HttpPost httpPost = new HttpPost(AIConstant.LOGIN_REGIST_URL + "?method=login");// 經過post傳遞 /** 綁定數據 這裏須要注意 若是是中文 會出現中文亂碼問題 但只要按設置好 */ MultipartEntity muit = new MultipartEntity(); File fileupload = new File(filePath+newfileName); FileBody fileBody = new FileBody(fileupload); muit.addPart("file", fileBody); httpPost.setEntity(muit); /** 發送請求 */ try { HttpResponse response = client.execute(httpPost); // 判斷師傅上傳成功 返回200 if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) { loginInfo = (com.alibaba.fastjson.JSONObject) com.alibaba.fastjson.JSONObject.parse(EntityUtils.toString(response .getEntity())); }else{ loginInfo.put("flag", false); loginInfo.put("message", "服務器相應異常!"); } } catch (ClientProtocolException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } out.write(loginInfo.toString()); } catch (Exception e) { e.printStackTrace(); } }
其中涉及到的圖片壓縮ImageCompressUtil.GenerateImage()類及方法參見博客: http://www.cnblogs.com/guo-eric/p/8418626.html 有詳細介紹
引入的三方文件有:apache
import org.apache.http.HttpResponse; import org.apache.http.HttpStatus; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpPost; import org.apache.http.entity.mime.MultipartEntity; import org.apache.http.entity.mime.content.FileBody; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.util.EntityUtils;
三、須要單獨寫一個web服務,發佈http接口用的,在這裏有第二步想要訪問的接口,接口編寫:json
package com.hengyunsoft.face.login; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.io.PrintWriter; import java.text.SimpleDateFormat; import java.util.Date; import javax.servlet.ServletException; import javax.servlet.annotation.MultipartConfig; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.Part; import org.json.JSONArray; import org.json.JSONObject; import sun.misc.BASE64Decoder; import com.baidu.aip.face.AipFace; import com.hengyunsoft.face.aip.FaceManage; import com.hengyunsoft.face.util.ImageCompressUtil; /** * Servlet implementation class UploadFile */ @WebServlet("/login.do") @MultipartConfig public class Login extends HttpServlet { private static final long serialVersionUID = 1L; // 設置APPID/AK/SK public static final String APP_ID = "10580034"; public static final String API_KEY = "CUEBLydMIEhyHXGgjuBLMCDx"; public static final String SECRET_KEY = "XXXXXX"; /** * @see HttpServlet#HttpServlet() */ public Login() { super(); // TODO Auto-generated constructor stub } /** * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse * response) */ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { try { String method = request.getParameter("method"); switch (method) { case "login": login_regist_inter(request, response);// 接口調用 break; case "reg": login_regist_inter(request, response);// 接口調用 break; case "del": del_inter(request, response);// 接口調用 break; default: break; } } catch (Exception e) { System.out.println("接口調用異常"); } } /** * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse * response) */ protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doGet(request, response); } /** * 登陸和註冊的接口 * * @param req * @param resp * @throws Exception */ public void login_regist_inter(HttpServletRequest req, HttpServletResponse resp) throws Exception { resp.setContentType("application/text; charset=utf-8"); PrintWriter out = resp.getWriter(); // 接口返回值 JSONObject returnValue = new JSONObject(); returnValue.put("flag", true); // 圖片上傳路徑 String filePath = req.getSession().getServletContext() .getRealPath("/upload") + File.separator; String fileName = getDate("yyyyMMddHHmmss") + ".png"; // 獲取接口傳遞參數 String uid = req.getParameter("uid"); String method = req.getParameter("method"); // 每次上傳文件以前,須要先將以前的文件刪除掉 File file = new File(filePath); if (file.isDirectory()) { for (File f : file.listFiles()) { f.delete(); } } // 文件夾位置固定,文件夾採用與上傳文件的原始名字相同 String fileSavingPath = filePath + fileName; // 若是存儲上傳文件的文件夾不存在,則建立文件夾 File f = new File(filePath); if (!f.exists()) { f.mkdirs(); } Part part = req.getPart("file");// 獲取文件路徑 part.write(fileSavingPath); // 拿到base64編碼的圖片,就能夠調用百度的API進行驗證 AipFace client = new AipFace(APP_ID, API_KEY, SECRET_KEY); if (method.equals("reg")) { register(filePath, fileName, returnValue, uid, client); } else if (method.equals("login")) { // 須要從返回的信息中取用戶id login(filePath, fileName, returnValue, client); } out.write(returnValue.toString()); } /** * 清除註冊信息的接口 * * @param req * @param resp * @throws Exception */ public void del_inter(HttpServletRequest req, HttpServletResponse resp) throws Exception { resp.setContentType("application/text; charset=utf-8"); PrintWriter out = resp.getWriter(); // 接口返回值 JSONObject returnValue = new JSONObject(); returnValue.put("flag", true); // 獲取接口傳遞參數 String uid = req.getParameter("uid"); // 拿到base64編碼的圖片,就能夠調用百度的API進行驗證 AipFace client = new AipFace(APP_ID, API_KEY, SECRET_KEY); try { FaceManage.deleteUser(client, uid); returnValue.put("message", "人臉信息刪除成功!"); } catch (Exception e) { returnValue.put("flag", false); returnValue.put("message", "人臉信息刪除失敗!"); } out.write(returnValue.toString()); } /** * 登陸的第二種實現,人臉識別的方式,將註冊用戶的全部匹配度拿到,取最高 * * @param filePath * @param fileName * @param j * @param uid * @param client * @return */ private void login(String filePath, String fileName, JSONObject aiInfo, AipFace client) { JSONObject aiJson = FaceManage .identifyUser(client, filePath + fileName); double tmp = 0.0, matchPercent = 0.0; String uid = ""; try { JSONArray ja = aiJson.getJSONArray("result"); double scores[] = new double[ja.length()]; // 聲明數組 matchPercent = scores[0]; for (int i = 0; i < ja.length(); i++) { JSONObject json = ja.getJSONObject(i); tmp = Double.parseDouble(json.get("scores").toString() .replace("[", "").replace("]", "")); if (tmp > matchPercent) { // 判斷最大值 matchPercent = tmp; uid = json.get("uid").toString(); } System.out.println(tmp); } } catch (Exception e) { matchPercent = 0.0; } if (matchPercent > 90) { System.out.println("驗證成功,人臉匹配度是:" + matchPercent); aiInfo.put("uid", uid); aiInfo.put("matchPercent", matchPercent); aiInfo.put("flag", true); aiInfo.put("message", "驗證成功,人臉匹配度是:" + matchPercent); } else { System.out.println("驗證失敗,人臉匹配度是:" + matchPercent); aiInfo.put("flag", false); aiInfo.put("uid", uid); aiInfo.put("matchPercent", matchPercent); aiInfo.put("message", "驗證失敗,人臉匹配度是:" + matchPercent); } } /** * 註冊 * * @param filePath * @param fileName * @param j * @param uid * @param client * @return */ private void register(String filePath, String fileName, JSONObject regInfo, String uid, AipFace client) { String message = "用戶" + uid + "人臉註冊失敗!"; int matchPercent = FaceManage.saveOrUpdateUser(client, filePath + fileName, uid); if (matchPercent == 1) { message = "用戶" + uid + "人臉註冊成功!"; regInfo.put("flag", true); } else { regInfo.put("flag", false); } regInfo.put("message", message); } public String getDate(String pattern) { return new SimpleDateFormat(pattern).format(new Date()); } }
須要注意的是:canvas
1)類上要加@MultipartConfig註解,該註解是用來保存上傳圖片的數組
2)須要引入Part類:javax.servlet.http.Part; 用來將上傳圖片寫入文件中
3)調用的人臉識別接口可參考博客:http://www.cnblogs.com/guo-eric/p/8109411.html
至此就完成了人臉識別登陸過程,登陸系統和人臉識別處理接口的服務相分離的實現,歡迎瞭解。