关于移动端拍照上传图片的解决方案
场景
产品要求用户拍一张身份证和一张人像,然后后台php调用商用接口比对证件和人像的匹配度。
方案1:使用上传插件web-upload
- 证件和人像分别上传到后台,然后返回图片地址,前端回显。
- 点击核验按钮,ajax再将返回的图片地址传到后台,后台将地址转成bases64,调用接口比对,返回结果。
缺点
- 手机拍照图片过大,webupload压缩后,图片依然大,没上传一次花费时间过长,最后再调用接口比对时间花费也长。
- webupload的样式需要重新定义
.webuploader-pick {
display: inline-block;
width: 1.6rem;
height: 1.6rem;
position: absolute;
left: 50%;
top: 50%;
-webkit-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
background-color: transparent;
}
- webupload的input框没办法限制用户只能调用摄像头。(webupload加载完成后会生成一个input框,但是页面加载后不能重新给input添加属性,只有在上传中才能获取到).
方案2:使用原生的H5对象完成上传
- 用户点击input按钮,调用FileReader对象生成file.
- 利用canvas压缩图片,context进行绘图回显。
- 再将base64码dataURL转为file.
- 利用FormData对象追加file.发送后台。
- 后台$_FILES接受后,转为base64发送到接口,获取结果。
缺点
1.流程稍显复杂。
2.兼容性问题。
// 扫描身份证
$('.input-card').on('change', function () {
var oFReader = new FileReader();
var card_files = document.getElementById('card-file').files[0];
oFReader.readAsDataURL(card_files);
oFReader.onloadend = function (oFRevent) {
img = new Image();
img.src = oFRevent.target.result;
img.onload = function () {
// 获取照片信息 等于6时照片会旋转90°
var photo = getPhotoOrientation(img);
// 压缩图片
var compress_data = compress(img);
// 将图片url转为file类型 (直接base64传到后台始终太大了)
card_img_file = dataURLtoFile(compress_data, 'img.png');
$(".crad-img").attr('src', img.src);
//$("#compress_card").attr('src', imgfile);
}
// 太大就进行压缩
}
})
// 图片压缩
function compress(img) {
canvas.width = img.width
canvas.height = img.height
//利用canvas进行绘图
context.drawImage(img, 0, 0); // 重要
//将原来图片的质量压缩到原先的0.2倍。
var data = canvas.toDataURL('image/jpeg', 0.1) //data url的形式
return data
}
// base64 转file
function dataURLtoFile(dataurl, filename) {
var arr = dataurl.split(','),
mime = arr[0].match(/:(.*?);/)[1],
bstr = atob(arr[1]),
n = bstr.length,
u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bstr.charCodeAt(n);
}
return new File([u8arr], filename, {
type: mime
});
}
//获取照片的元信息(拍摄方向)
function getPhotoOrientation(img) {
var orient;
EXIF.getData(img, function () {
orient = EXIF.getTag(this, 'Orientation');
});
return orient;
}
//确定核验
$('#saveDate').on('click', function () {
var _token = $('meta[name="csrf-token"]').attr('content');
var formData = new FormData();
formData.append("_token", _token); // 追加token
formData.append("order_room_id", order_room_id); // 追加其他项目参数
formData.append("face_img_file", face_img_file); // 追加文件
formData.append("card_img_file", card_img_file);
msg = layer.open({
type: 2,
content: '核验中'
});
$.ajax({
url: '/check-in/ajax-real',
type: 'post',
data: formData,
cache: false,
processData: false, // 必填参数
contentType: false, // 必填参数
async: false,
dataType: 'json',
success: function (data) {
layer.close(msg);
if (data.status == 'success') {
layer.open({
content: data.msg,
skin: 'msg',
time: 2,
end: function (layero, index) {
// 跳转table页
window.location.href =
"{{Route('check.table',['num'=>$total_num,'order_room_id'=>$order_room_id])}}";
}
});
} else {
layer.open({
content: data.msg,
skin: 'msg',
time: 3
});
}
}
});
})
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。