前端
<template>
<div style="padding-top: 5px;text-align: center" @click="imgClick()">
<van-button color="#1EC7A6" :icon="require('../assets/icon/shoot.jpg')" type="info">拍照识别身份证</van-button>
<input v-if="clearShow" style="float: left; display: none;" type="file" id='uploadFile' accept="image/*" @change="takePhoto($event)">
</div>
</template>
<script>
export default {
data() {
return {
info:{
},
clearShow:true
}
},
methods: {
takePhoto(e){//拍照功能---上传头像
this.clearShow = false;
var file=e.target.files[0]//获取文件对象
let self = this;
let Orientation;
let ndata;
if(file.size<=1* 1024* 1024){
//判断图片是否大于1M,是就直接上传
ndata=file;
self.postImg(ndata);
}else{
//反之压缩图片
let reader = new FileReader();
// 将图片2将转成 base64 格式
reader.readAsDataURL(file);
console.log(reader)
// 读取成功后的回调
reader.onloadend = function () {
let result = this.result;
let img = new Image();
img.src = result;
img.onload = function () {
let data = self.compress(img, Orientation);
self.headerImage = data;
ndata = self.compress(img, Orientation);
//BASE64转图片
var arr = ndata.split(','), mime = arr[0].match(/:(.*?);/)[1],
bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bstr.charCodeAt(n);
}
ndata = new File([u8arr], file.name, {type: mime})
self.postImg(ndata);
}
}
}
// this.uploadImg(file);
},
//删除图片
//图片click
imgClick:function(){
document.getElementById("uploadFile").click();
},
async postImg(blob) {
let filename = `${new Date().getTime()}.jpg`;
let file = new File([blob], filename, {type: 'image/jpg'});
let formData = new FormData();
formData.append('file', file);
formData.append('parentPath', "sign");//这个不是必须的,只是我自己设计的后台保存代码
let data = await this.$net.uploadImg({
url: this.$url.common.uploadImageToService,
data: formData
});
this.clearShow = true;
console.log(data)
console.log(data.data.data.url);
let getInfo= await this.$net.post({
url: this.$url.hosApi.getAccessToken,
data: {
img:data.data.data.url
}
});
console.log(getInfo);
if (getInfo.code==200){
this.info=getInfo.data;
}else{
alert(getInfo.msg)
}
},
compress(img,Orientation) {
let canvas = document.createElement("canvas");
let ctx = canvas.getContext('2d');
//瓦片canvas
let tCanvas = document.createElement("canvas");
let tctx = tCanvas.getContext("2d");
let initSize = img.src.length;
let width = img.width;
let height = img.height;
//如果图片大于四百万像素,计算压缩比并将大小压至400万以下
let ratio;
if ((ratio = width * height / 4000000) > 1) {
console.log("大于400万像素")
ratio = Math.sqrt(ratio);
width /= ratio;
height /= ratio;
} else {
ratio = 1;
}
canvas.width = width;
canvas.height = height;
// 铺底色
ctx.fillStyle = "#fff";
ctx.fillRect(0, 0, canvas.width, canvas.height);
//如果图片像素大于100万则使用瓦片绘制
let count;
if ((count = width * height / 1000000) > 1) {
console.log("超过100W像素");
count = ~~(Math.sqrt(count) + 1); //计算要分成多少块瓦片
// 计算每块瓦片的宽和高
let nw = ~~(width / count);
let nh = ~~(height / count);
tCanvas.width = nw;
tCanvas.height = nh;
for (let i = 0; i < count; i++) {
for (let j = 0; j < count; j++) {
tctx.drawImage(img, i * nw * ratio, j * nh * ratio, nw * ratio, nh * ratio, 0, 0, nw, nh);
ctx.drawImage(tCanvas, i * nw, j * nh, nw, nh);
}
}
} else {
ctx.drawImage(img, 0, 0, width, height);
}
//修复ios上传图片的时候 被旋转的问题
if(Orientation != "" && Orientation != 1){
switch(Orientation){
case 6://需要顺时针(向左)90度旋转
this.rotateImg(img,'left',canvas);
break;
case 8://需要逆时针(向右)90度旋转
this.rotateImg(img,'right',canvas);
break;
case 3://需要180度旋转
this.rotateImg(img,'right',canvas);//转两次
this.rotateImg(img,'right',canvas);
break;
}
}
//进行最小压缩
let ndata = canvas.toDataURL('image/jpeg', 0.1);
console.log('压缩前:' + initSize);
console.log('压缩后:' + ndata.length);
console.log('压缩率:' + ~~(100 * (initSize - ndata.length) / initSize) + "%");
tCanvas.width = tCanvas.height = canvas.width = canvas.height = 0;
return ndata;
}
}
}
</script>
后端
上传图片
@PostMapping("uploadImg")
public Result uploadContentImg(@RequestParam("parentPath") String parentPath, @RequestParam("file") MultipartFile file) throws IOException {
String fileName = file.getOriginalFilename();
fileName = fileName.substring(fileName.lastIndexOf("."));//截取后缀
fileName = System.currentTimeMillis()+ MyUtil.getRandomString(6)+fileName;//添加后缀
String serviceLocalPath =getRealPath(parentPath,fileName);
File realFile = new File(serviceLocalPath);
realFile.getParentFile().mkdirs();
//4.把浏览器上传的文件保存到本地
file.transferTo(realFile);
String path = parentPath+"/"+fileName;
String host = getImgHomeUrl(httpRequest);
UploadImage bean = new UploadImage();
bean.setPath(serviceLocalPath);
bean.setHost(host);
bean.setUrl(host+path);
return ResultGenerator.genSuccessMessage(bean);
}
//获取网站图片地址
public static String getImgHomeUrl(HttpServletRequest req) {
String basePath = null;
if(getHostPath()!=null){
basePath = getHostPath() + req.getContextPath();
}else{
basePath = req.getScheme() + "://" + req.getServerName() + ":" + req.getServerPort() + req.getContextPath();
}
return basePath + getStaticAccessPath();
}
public static String getRealPath(String parentFileName,String filename) {
return getUploadFolder()+ File.separator+ parentFileName +File.separator+filename;
}
调用微信ocr
@RequestMapping(value = "/getAccessToken", method = RequestMethod.POST)
public Result getAccessToken(@RequestBody Map map) {
//获取本地缓存accessToken
String accessToken = WeChatCache.ACCESS_TOKEN.get(hosUserService.getHosUserByToken(SysContent.getHeader().getToken()).getCurrentPlatId().toString());
String url="https://api.weixin.qq.com/cv/ocr/idcard?img_url="+map.get("img")+"&access_token="+accessToken;
JSONObject forObject = restTemplate.getForObject(url, JSONObject.class);
if (!StringUtils.isEmpty(forObject.getString("errcode")) && "0".equals(forObject.getString("errcode"))) {
return ResultGenerator.genSuccessMessage(forObject);
}else {
throw new YXException(forObject.getString("errmsg"));
}
}