我的需求是, 打开摄像头, 拍照后, 把文件上传到服务器; 过程不是很顺利, 所以记录一下. 放置打开摄像头的按钮的页面就不写了, 主要写摄像头页面;
注意: 服务必须是安全链接 https 的才可以, 否则无法使用摄像头
<template>
<div>
<el-row :gutter="16">
<el-col :span="12">
<!--图片展示-->
<video ref="video" :width="canvasW" :height="canvasH" autoplay/>
</el-col>
<el-col :span="12" >
<!--canvas截取流-->
<div class="avatar-uploader">
<canvas ref="canvas" :width="canvasW" :height="canvasH"/>
</div>
</el-col>
</el-row>
<el-row class="camera-button" :gutter="16">
<!--确认-->
<el-col :span="12">
<el-button type="primary" @click="photograph">拍照</el-button>
</el-col>
<el-col :span="12">
<el-button type="primary" @click="refreshCanvas" plain>重拍</el-button>
</el-col>
</el-row>
</div>
</template>
<script>
import store from "../../../store";
export default {
props:['fileName','customerId',],
data() {
return {
action: `filedoc/file/doc/uploadUnusedSingle`,
addFaceAction: 'basicdata/thirdParty/face/upload',
checkFaceAction: 'basicdata/thirdParty/face/check',
headImgSrc: '/img/code/wechat-code.jpg',
canvasH: 340,
canvasW: 401,
imgBase64: '',
faceFiles: [],
}
},
mounted() {
let _this = this;
this.callCamera();
// 查询门禁图片
this.postRequest("basicdata/thirdParty/face/get", {customerId: _this.customerId}, function(data) {
_this.faceFiles = data;
});
},
beforeDestroy() {
this.closeCamera();
},
methods: {
// 调用摄像头
callCamera() {
// H5调用电脑摄像头API, 指定最低像素, 期望像素和最高像素
navigator.mediaDevices.getUserMedia({
video: { width: { min: 1280, ideal: 1920, max: 1920 },
height: { min: 720, ideal: 1080, max: 1080 }
}
}).then(success => {
// 摄像头开启成功
this.$refs['video'].srcObject = success;
// 实时拍照效果
this.$refs['video'].play();
}).catch(error => {
console.error('摄像头开启失败,请检查摄像头是否可用!')
})
},
// 拍照
photograph() {
let ctx = this.$refs['canvas'].getContext('2d');
// 把当前视频帧内容渲染到canvas上
ctx.drawImage(this.$refs['video'], 0, 0, this.canvasW, this.canvasH);
// 转base64格式、图片格式转换、图片质量压缩
this.imgBase64 = this.$refs['canvas'].toDataURL('image/jpeg');
// 由字节转换为KB 判断大小
// let imgCode = this.imgBase64.replace('data:image/jpeg;base64,', '');
// // 图片尺寸 用于判断
// let strLength = imgCode.length;
// let fileLength = parseInt(strLength - (strLength / 8) * 2);
// let size = (fileLength / 1024).toFixed(2);
// 保存到本地
// let ADOM = document.createElement('a');
// ADOM.href = this.headImgSrc;
// ADOM.download = new Date().getTime() + '.jpeg';
// ADOM.click();
},
// 清除照片
refreshCanvas() {
let ctx = this.$refs['canvas'].getContext('2d');
ctx.clearRect(0, 0, this.canvasW, this.canvasH);
this.imgBase64 = '';
},
// 关闭摄像头
closeCamera() {
if (!this.$refs['video'].srcObject) return;
let stream = this.$refs['video'].srcObject;
let tracks = stream.getTracks();
tracks.forEach(track => {
track.stop()
});
this.$refs['video'].srcObject = null;
},
// 上传前的校验
beforeAvatarUpload(file) {
// 最大664 KB
const isLt2M = file.size / 1024 < 646;
if (!isLt2M) {
this.$message({
message: '上传头像图片大小不能超过 646KB!',
type: 'warning'
});
}
return isLt2M;
},
// 上传人脸信息, 绑定文件和人员关系
uploadAvatar() {
let _this = this;
if(!this.imgBase64){
this.$message({
message: '请拍摄照片后再上传',
type: 'warning'
});
return;
}
let file = this.dataURLtoFile(this.imgBase64, this.fileName);
let faceBase64 = this.imgBase64.replace('data:image/jpeg;base64,', '').replace('data:image/jpg;base64,', '');
if(this.beforeAvatarUpload(file)){
let formData = new FormData();
const userId = store.getters["login/userId"];
formData.append("uploadUserId", userId);
formData.append('file', file);
this.uploadFileRequest(this.action, formData, data =>{
if(data && data.id){
let param = {customerId: _this.customerId, fileId: data.id, faceBase64};
this.postRequest(this.addFaceAction, param, data=>{
if(data==="success"){
this.$emit('getFace', _this.customerId);
this.$notify({
title: '成功',
message: '上传成功',
type: 'success'
});
this.$emit('closeCamera');
}else{
this.$message({
message: data,
type: 'warning'
});
}
});
}
});
}
},
//将base64转换为blob
dataURLtoBlob(dataurl) {
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 Blob([u8arr], { type: mime });
},
// 将blob转换为file
blobToFile(theBlob, fileName){
theBlob.lastModifiedDate = new Date();
theBlob.name = fileName;
return new File([theBlob], fileName);
},
// base64 转 file
dataURLtoFile(dataurl, filename='faceImg.jpg') {
let blobT = this.dataURLtoBlob(dataurl);
return this.blobToFile(blobT,filename);
}
}
}
</script>
<style scoped>
.camera-button {
text-align: center;
width: 100%;
margin: 0.2rem 0 0 0;
}
.avatar-uploader {
border: 1px dashed #d9d9d9;
border-radius: 6px;
cursor: pointer;
position: relative;
overflow: hidden;
width: 401px;
height: 300px;
margin: 20px auto;
}
</style>