调用http接口并实现图片传递的关键分为两部分
其一:创建servlet接口,加图片上传注解,用于接收传过来的图片等信息,并做进一步的处理后,返回json格式的结果
其二:创建htpclient,并且运用MultipartEntity对图片进行封装,调用http接口,获取返回值,进行下一步处理
下面就以人脸识别登录,来讲解带有图片的http接口的调用过程
1、创建jsp页面,用于获取到人脸信息
<%@ 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 { 340px; background:#ccc; border: 10px solid #ddd; margin: 0 auto; } .btn input[type=button] { 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>
2、在loginController中编写创建httpclient的方法,并调用接口、
/** * 调用接口,实现人脸识别登录 * @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 有详细介绍
引入的三方文件有:
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;
3、需要单独写一个web服务,发布http接口用的,在这里有第二步想要访问的接口,接口编写:
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()); } }
需要注意的是:
1)类上要加@MultipartConfig注解,该注解是用来保存上传图片的
2)需要引入Part类:javax.servlet.http.Part; 用来将上传图片写入文件中
3)调用的人脸识别接口可参考博客:http://www.cnblogs.com/guo-eric/p/8109411.html
至此就完成了人脸识别登录过程,登录系统和人脸识别处理接口的服务相分离的实现,欢迎了解。