- 理清需求,明确要实现功能
- 查阅API文档,安装中间件
- 代码编写
- 功能完成
一、需求明确
- 使用高拍仪摄像头进行拍照(数据采集)
- 将采集的数据进行(预览、删除、合并)操作
- 文件合并,将多个数据合并成pdf文件(进行上传)
- 不合并,单文件展示(进行上传)
二、中间件(启动)
作用:底层主要实现与客户端交互,读取文件信息,文件类型转换等。由集成商提供
三、代码编写
- 初始化容器,获取摄像头,获取分辨率,代码如下:
// 初始化摄像头
loadCameraDocument() {
if (!window.WebSocket) {
alert("浏览器不支持HTML5,请更新浏览器或者使用其它浏览器");
}
var obj = document.getElementById("CameraCtl");
Cam_ControlInit(obj, 0, 0, 600, 400, (list,resolution)=> {
this.loading = false
// 获取设备
if (list?.length) {
this.deviceOptions=[]
list.forEach((item,index) => {
this.deviceOptions.push({value:index,label:item})
})
}
// 获取分辨率
if (resolution?.length) {
this.resolutionOptions=[]
resolution.forEach((item,index) => {
this.resolutionOptions.push({value:index,label:item})
})
}
}, (msg)=> {
// 启动失败
this.$message({
showClose: true,
message: msg||'设备开启失败,请重新尝试启动!',
type: 'error'
})
this.loading = false
this.noFindDevice=true
});
},
//*************摄像头操作初始化***************
var initCallback
var faileCallback
function Cam_ControlInit(documentObj, mX, mY, mwidth, mheight, callback,failBack) {
initCallback = callback
faileCallback=failBack
WebSocketConnect(); // 检测设备状态(心跳机制)
InitCanvas(documentObj, mX, mY, mwidth, mheight); // 渲染容器
//console.log("Cam_ControlInit");
}
//*************获取设备数目***************
function Cam_GetDevCount() {
GetDevCount();
}
//***************获取分辨率***************
var newSelectedIndex
function Cam_GetDevResolution(iCamNo) {
newSelectedIndex = iCamNo
GetResolution(iCamNo);
}
- 进行拍照,返回结果(base64),代码如下:
<el-button type="success" @click="toTakePhoto">拍照</el-button>
// 拍照
toTakePhoto() {
var name = this.formatDate(new Date().getTime());
var selectedIndex=0
var path;
Cam_SetFileType(selectedIndex); //设置文件格式
if (selectedIndex == 1) {
path = "D:\\" + name + ".png";
}
else if (selectedIndex == 2) {
path = "D:\\" + name + ".tif";
}
else if (selectedIndex == 3) {
path = "D:\\" + name + ".pdf";
}
else {
path = "D:\\" + name + ".jpg";
}
Cam_Photo(path, (src) => {
this.imgsList.push({
checked: true,
src,
fileName: name + ".jpg"
})
}); //主摄像头拍照
},
//*************拍照***************
var newCallback
function Cam_Photo(fileAddr, callback) {
newCallback=callback
if (MainCamCutMode == 2) {
var rectx, recty, rectw, recth;
if (pALastX > pACurrentX)
rectx = pACurrentX;
else
rectx = pALastX;
if (pALastY > pACurrentY)
recty = pACurrentY;
else
recty = pALastY;
rectw = Math.abs(pACurrentX - pALastX);
recth = Math.abs(pACurrentY - pALastY);
SetCutRect(rectx, recty, rectw, recth); //手动裁剪区域
}
CaptureImage(fileAddr);
}
//拍照结果返回 base64Str 字符串
if (rDataArr[2] == 0x10) {
var flag;
if (rDataArr[3] == 0x01) {
flag = 0;
var imgpathLen = rDataArr[4] * 256 + rDataArr[5];
if (imgpathLen == 0) {
var base64Len = rDataArr[6] * 65536 + rDataArr[7] * 256 + rDataArr[8];
var imgPathStr = "";
var base64Data = new Uint8Array(base64Len);
for (var i = 0; i < base64Len; i++) {
base64Data[i] = rDataArr[9 + imgpathLen + i];
}
var base64Str = Uint8ArrayToString(base64Data);
GetCaptrueImgResultCB(flag, imgPathStr, base64Str);
}
else {
var base64Len = rDataArr[6] * 65536 + rDataArr[7] * 256 + rDataArr[8];
var pData = new Uint8Array(imgpathLen);
for (var i = 0; i < imgpathLen; i++) {
pData[i] = rDataArr[9 + i];
}
var str = byteToString(pData);
var imgPathStr = decodeURIComponent(str);
var base64Data = new Uint8Array(base64Len);
for (var i = 0; i < base64Len; i++) {
base64Data[i] = rDataArr[9 + imgpathLen + i];
}
var base64Str = Uint8ArrayToString(base64Data);
GetCaptrueImgResultCB(flag, imgPathStr, base64Str);
}
}
if (rDataArr[3] == 0x02) {
flag = 2;
GetCaptrueImgResultCB(flag, "", "");
}
}
- 文件删除,代码如下:
// 删除文件
toDeleteFile(index, name) {
this.isDisabled = true
this.$confirm('您确定要删除该文件, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
var path = `D:\\${name}`;
this.imgsList.splice(index,1)
DeleteFile(path);
this.isDisabled = false
}).catch(() => {
this.isDisabled = false
});
},
function DeleteFile(filePath) {
if (isSocketConnect) {
if (filePath == "") {
var packageCount = 1;
var len = 0;
var pindex = 0;
var totalLen = 11;
var aDataArray = new Uint8Array(totalLen);
aDataArray[0] = 0x77;
aDataArray[1] = 0x88;
aDataArray[2] = 0xA8;
aDataArray[3] = len >> 16 & 0xff;
aDataArray[4] = len >> 8 & 0xff;
aDataArray[5] = len & 0xff;
aDataArray[6] = packageCount >> 8 & 0xff; //包总数
aDataArray[7] = packageCount & 0xff; //包总数
aDataArray[8] = 0; //分包长度
aDataArray[9] = pindex >> 8 & 0xff; //包序号
aDataArray[10] = pindex & 0xff; //包序号
console.log("pindex:" + pindex);
socket.send(aDataArray.buffer);
}
else {
var path = encodeURI(filePath);
console.log(path);
var pathArray = stringToByte(path);
var len = pathArray.length;
var packageCount = 0;
var tmpLen = len;
while (tmpLen > 0) {
tmpLen = tmpLen - 90;
packageCount++;
}
console.log("packageCount:" + packageCount);
var pindex = 0;
tmpLen = len;
while (tmpLen > 0) {
tmpLen = tmpLen - 90;
if (tmpLen > 0) {
var totalLen = 90 + 11;
var aDataArray = new Uint8Array(totalLen);
aDataArray[0] = 0x77;
aDataArray[1] = 0x88;
aDataArray[2] = 0xA8;
aDataArray[3] = len >> 16 & 0xff;
aDataArray[4] = len >> 8 & 0xff;
aDataArray[5] = len & 0xff;
aDataArray[6] = packageCount >> 8 & 0xff; //包总数
aDataArray[7] = packageCount & 0xff; //包总数
aDataArray[8] = 90; //分包长度
aDataArray[9] = pindex >> 8 & 0xff; //包序号
aDataArray[10] = pindex & 0xff; //包序号
console.log("pindex:" + pindex);
for (var i = 0; i < 90; i++) {
aDataArray[11 + i] = pathArray[i + pindex * 90];
}
socket.send(aDataArray.buffer);
}
else {
var totalLen = 90 + tmpLen + 11; // 此时tmpLen为负数,做加法运算
var aDataArray = new Uint8Array(totalLen);
aDataArray[0] = 0x77;
aDataArray[1] = 0x88;
aDataArray[2] = 0xA8;
aDataArray[3] = len >> 16 & 0xff;
aDataArray[4] = len >> 8 & 0xff;
aDataArray[5] = len & 0xff;
aDataArray[6] = packageCount >> 8 & 0xff; //包总数
aDataArray[7] = packageCount & 0xff; //包总数
aDataArray[8] = 90 + tmpLen; //分包长度
aDataArray[9] = pindex >> 8 & 0xff; //包序号
aDataArray[10] = pindex & 0xff; //包序号
console.log("pindex:" + pindex);
for (var i = 0; i < (90 + tmpLen); i++) {
aDataArray[11 + i] = pathArray[i + pindex * 90];
}
socket.send(aDataArray.buffer);
}
pindex++;
toSleep(80);
}
}
}
}
- 4 .文件合并,代码如下:
// 合并为pdf(先添加,后合并)
toMergePDFFile() {
Cam_AddImgFileToPDF("");
this.sleep(300);
Cam_CombinePDF(`D:\\${this.generateRandomString(20)}.pdf`, (data) => {
base64Data = data
fileName=`${this.generateRandomString(20)}.pdf`
this.toHttpUploadFile()
});
},
sleep(milliSeconds) {
var startTime = new Date().getTime();
while (new Date().getTime() < startTime + milliSeconds);
},
- 5.其他功能,代码如下:
//对焦
toCamFocus() {
Cam_Focus()
},
//切换图像质量
toSetJpgQuality() {
var val = this.imageQualityOptions[this.imageQuality].label;
Cam_SetJpgQuality(val);
},
// 属性
toShowVideoProp() {
Cam_ShowVideoProp()
},
// 左旋转
toRotateLeft() {
Cam_RotateLeft()
},
// 右旋转
toRotateRight() {
Cam_RotateRight()
},
- 6.文件上传
// 文件上传
toHttpUploadFile() {
filesList=[]
UpladFile(base64Data, fileName, (data,file) => {
api.addFileRecord(data).then(res => {
const {fileName,address,id } = res.data
this.submitLoading = false
this.addDialogVisible=false
filesList.push({
name:fileName,
url: address,
id
})
fileIds.push(id)
fileUrls.push(address)
this.$emit('update',fileIds,fileUrls,filesList)
api.uploadFile(res.data, file)
})
})
},
// base64转换为对应的文件类型
function dataURLtoFile(dataurl, filename) {
var bstr = atob(dataurl);
var n = bstr.length;
var u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bstr.charCodeAt(n);
}
var suffix = filename.substring(filename.length - 3, filename.length);
if (suffix == "jpg" || suffix == "JPG")
return new File([u8arr], filename, { type: 'image/jpg' });
if (suffix == "png" || suffix == "PNG")
return new File([u8arr], filename, { type: 'image/png' });
if (suffix == "tif" || suffix == "TIF")
return new File([u8arr], filename, { type: 'image/tiff' });
if (suffix == "pdf" || suffix == "PDF")
new File([u8arr], filename, { type: 'application/pdf' });
return new File([u8arr], filename, { type: 'application/jpg' });
}
// 将文件转为FormData
function UpladFile(base64data, fileName, callback) {
//base64数据转为文件对象
var fileObj = dataURLtoFile(base64data, fileName);
var fm = document.forms[0];
var form = new FormData(fm);
const { name, size } = fileObj;
form.append('fileName', name);
form.append('size', size);
console.log('文件信息'+JSON.stringify(fileObj))
callback(form,fileObj);
}
四、功能完成
总结:
- 在切换摄像头时、要重新获取对应摄像头的分辨率信息,否则设备会渲染失败
- 文件上传,要将获取到的base64进行转换
- 文件在上传时,要先处理合并逻辑,反之无法上传
- 文件删除,文件路径要选择正确,反之无法删除本地文件