vue+Element-UI通过ActiveX 控件,实现扫描文件到本地并上传到服务器
最近项目有个需求:将文件通过购买的富士通扫描仪扫描到本地,扫描完成后自动上传到服务器,并关联相关单据。其间遇到相关问题如下:1.购买的富士通扫描仪提供的开发文档要求必须使用IE中的...
·
最近项目有个需求:将文件通过购买的富士通扫描仪扫描到本地,扫描完成后自动上传到服务器,并关联相关单据。
相关注意事项如下:
1.购买的扫描仪提供的开发文档说是使用ActiveX 控件,所以必须用IE浏览器,且必须是windows环境
2.使用vue开发的项目,需要使用vue接入ActiveX控件
3.将扫描到本地的文件自动上传到服务器上
4.更新表单文件
具体实现方法如下:
首先在index.html中初始化扫描仪:
<script>
//初始化扫描仪配置
/*orderDocument表示当前单据编号,用于给扫描后的文件命名。length是为了给文件有序化命名,比如当前扫描了两个文件(orderDocument_001.jpg,orderDocument_002.jpg,),下次再次扫描的时候方便从_003开始全名*/
function InitSettings (orderDocument,length) {
/*FileName 本属性设置储存图像数据的文件名称(不包括扩展名);
*储存图像数据的文件名称(包括绝对路径,以“\0”结束); 不要指定扩展名,由控件根据 FileType 属性指定;
* 本属性只在 ScanTo 属性为“0 – 文件”时有效; 实际的文件名称通过以下方式确定:在本属性指定的文件名后面添加三位数字序列号, 后面是 FileType 属性指定的图像数据类型的扩展名;
例如,当 FileType 属性设置为“1 - TIFF”且 FileName 属性设置为“C:\image\img”时扫 描三个文件,则在 C:\image\文件夹中创建名为 img001.tif、img002.tif 和 img003.tif 的三 个图像文件;
如果存在同名文件,则会根据 Overwrite 属性设定值来处理; 如果指定文件名中包含“\ * ? “ < > |”中的任意非法字符,则无法创建文件; 可以使用“#”通配符来指定 1 至 5 位数字序列号,
例如:
img# img###vvv img#####v
-> img1
-> img001vvv -> img00001v
当 FileNumber2 设置为-1 时,将不会在文件名中添加数字序列号;
* */
fhkScan.FileName = 'D:\\scanImage\\'+orderDocument+'_';
fhkScan.FileNumber2 = parseInt(length);
/*PixelType 像素类型: 0 – 黑白(初始值) 1 – 灰度 2 – 彩色 3 – 自动
说明
本属性用于设置将要读取的像素数据类型;
当 FileType 属性设置为“3 - JPEG”时,本属性不能设置为“0 – 黑白”;
当 CompressionType 属性设置为“0 – 无压缩”时,本属性才能设置为“3 – 自动”;
*/
fhkScan.PixelType = 2;
/* FileType 文件类型(图像数据格式) 0 – BMP : Windows 位图文件 1 – TIFF : TIFF 文件(初始值)
2– 多页TIFF: 多页TIFF文件 3 – JPEG : JPEG 文件
4 – PDF : PDF 文件
5– 多页PDF: 多页PDF文件
本属性只在 ScanTo 属性为“0 – 文件”时有效;
当本属性设置为“1 – TIFF”或“2 – 多页 TIFF”,PixelType 属性设置为“1 – 灰度”或“2 – 彩色”时,CompressionType 属性必须设置为“0 – 无压缩”或“5 – JPEG”;
当本属性设置为“3 – JPEG”时,PixelType 属性必须设置为“1 – 灰度”或“2 – 彩色”; 当本属性设置为“4 – PDF”或“5 – 多页 PDF”时,如果 PixelType 属性设置为“0 – 黑 白”,则 CompressionType 属性必须设置为“5 – JPEG”以外的任何值;如果 PixelType 属 性设置为“1 – 灰度”或“2 – 彩色”时,CompressionType 属性必须设置为“0 – 无压 缩”或“5 – JPEG”;
*
* */
fhkScan.FileType = 3;
/*CompressionType 数据压缩类型
0 – 无压缩
1 – CCITT G3(1D) : MH 压缩
2 – CCITT G3(2D) KFactor = 2 : MR 压缩,K Factor 为 2
3 – CCITT G3(2D) KFactor = 4 : MR 压缩,K Factor 为 4
4 – CCITT G4 : MMR 压缩(初始值)
5 – JPEG : JPEG 压缩
本属性在如下情况下有效:ScanTo 属性设置为“0 – 文件”且 FileType 属性设置为“1 – TIFF”、“2 – 多页 TIFF”、“4 – PDF”、“5 – 多页 PDF”或者 ScanTo 属性设置为“2 – 原始 图像句柄”;其他情况下忽略本属性;
当 FileType 属性设置为“0 – BMP”时,本属性自动设定为“0 – 无压缩”;
当 FileType 属性设置为“3 – JPEG”时,本属性自动设定为“5 – JPEG”; 本属性的设定值中“1 – CCITT G3(1D)”、“2 – CCITT G3(2D) KFactor = 2”、“3 – CCITT G3(2D) KFactor = 4”、“4 – CCITT G4”适用于黑白数据,“5 – JPEG”适用于彩色数据;
如果 PixelType 属性设置为“1 – 灰度”或“2 – 彩色”,而本属性设置为适用于黑白数 据的压缩方式,则扫描将会被设定为黑白模式,即 PixelType 属性自动设定为“0 – 黑白”;
* */
fhkScan.CompressionType = 5;
/* JPEG 数据压缩水平
*设定值
0 – 水平 1 : 压缩水平 1(文件大小优先)
1 – 水平 2 : 压缩水平 2
2 – 水平 3 : 压缩水平 3
3 – 水平 4 : 压缩水平 4
4 – 水平 5 : 压缩水平 5(初始值)
5 – 水平 6 : 压缩水平 6
6 – 水平 7 : 压缩水平 7(图像质量优先)
* */
fhkScan.JPGQuality = 2;
/*PaperSupply进纸模式
0 – 平板 1 – ADF 正面(初始值) 2 – ADF 双面
当设备支持平板时才能设置本属性为“0 – 平板”;当设备支持 ADF 时才能设置本属性 为“1 – ADF 正面”或“2 – ADF 双面”;
* */
fhkScan.PaperSupply = 1;
fhkScan.ScanRotate = 0;
fhkScan.Resolution = 7;// 800x800 dpi
fhkScan.SkipWhitePage = 6;
fhkScan.ShowSourceUI = false;
fhkScan.Overwrite = 1;
fhkScan.SilentMode = false;
/*ScanTo 扫描数据输出方式
*0 – 文件(初始值)
1 – DIB 句柄
2 – 原始图像句柄
本属性设置扫描仪读取的图像数据的输出目的地;
当设置为“0 – 文件”时,图像数据输出至文件,参见 FileName 和 FileType 属性; 当设置为“1 – DIB 句柄”时,响应 ScanToDib 事件,获取 DIB 句柄;
当设置为“2 – 原始图像句柄”时,响应 ScanToRaw 事件,获取图像内存句柄;
* */
fhkScan.ScanTo = 0;
/*ScanCount 扫描纸张数目
-1 或 1 – 32767(页数) 指定-1,扫描 ADF 上的所有纸张(初始值)
*本属性仅在 PaperSupply 属性设置为“1 – ADF 正面”或“2 – ADF 双面”时有效;
当 PaperSupply 属性设置为“0 – 平板”时,仅扫描一次;
当本属性设置为 1,而 PaperSupply 属性设置为“2 – ADF 双面”时,仅扫描纸张的正面, 若要扫描双面,则本属性需要设置为 2;
* */
fhkScan.ScanCount = -1;
/*DetectPageSize 检测纸张尺寸
*0 – 不检测(初始值)
1 – 页尾检测
2 – 自动页面检测 3 – 黑色背景检测 4 – 自动纠偏
用于选择扫描的页面检测模式;
* */
fhkScan.DetectPageSize = 2;
fhkScan.SourceCurrentScan = false
}
//实时更新扫描文件
function OnScanToFileEvent(scanFilePath)
{
var txtResults = document.getElementById("result");
var str = txtResults.value;
str += scanFilePath;
str += "\r\n";
txtResults.value = str;
}
</script>
然后在html中
<!--调用ActiveX控件-->
<object id="fhkScan" width="0" height="0" classid="clsid:******">
</object>
<!--记录扫描后的文件名及文件目录-->
<input id="result" type="hidden" readonly="readonly" />
<div id="app"></div>
<!--扫描事件-->
<script for="fhkScan" event="ScanToFile(scanFilePath)">
OnScanToFileEvent(scanFilePath);
</script>
然后是扫描按钮,使用的是Element-UI
<el-button type="danger" plain @click="scanDocument" >扫描
</el-button>
scanDocument(){
InitSettings(this.orderDocument,this.docList.length+1)
//OpenScanner 初始化,获得扫描仪信息 应用程序在调用 StartScan 方法之前必须先调用本方法;
// 返回值
// 0 : RC_SUCCESS – 正常终止
// 2 : RC_NOT_DS_FJTWAIN – 非 FUJITSU TWAIN 驱动
// -1 : RC_FAILURE – 错误
var rtn = fhkScan.OpenScanner(0)
if (rtn == -1) {
alert('打开扫描仪出错,错误代码为' + fhkScan.ErrorCode)
return
}
/*StartScan ... 开始扫描
返回值
0 : RC_SUCCESS – 正常终止
1 : RC_CANCEL – 用户取消或者发生导致设备无法继续扫描的错误(如内存不足等)
-1 : RC_FAILURE – 错误
*调用本方法之前,务必先调用 OpenScanner 开启扫描仪; 本方法执行结束以后,务必调用 CloseScanner 结束扫描;
* */
rtn = fhkScan.StartScan(0)
if (rtn == -1) {
fhkScan.CloseScanner(0)
if (fhkScan.ErrorCode==1||fhkScan.ErrorCode==21) {
alert('设备正在初始化,等待设备准备就绪后再重试')
} else if (fhkScan.ErrorCode==2||fhkScan.ErrorCode==3||fhkScan.ErrorCode==5||fhkScan.ErrorCode==39||fhkScan.ErrorCode==40||fhkScan.ErrorCode==54){
alert('请检查纸张,再重试')
} else if (fhkScan.ErrorCode==4){
alert('请关闭 ADF 盖板,再重试')
} else if (fhkScan.ErrorCode==11){
alert('设备可能被锁定,参照设备的用户指南')
} else if (fhkScan.ErrorCode==15||fhkScan.ErrorCode==16||fhkScan.ErrorCode==17||fhkScan.ErrorCode==18||fhkScan.ErrorCode==19||fhkScan.ErrorCode==20){
alert('非法操作或未知的设备问题,重启电脑和扫描仪设备再重试')
}else if (fhkScan.ErrorCode==22||fhkScan.ErrorCode==44){
alert('设备内置内存可能不足,请减小扫描图像尺寸再重试')
}else if (fhkScan.ErrorCode==24||fhkScan.ErrorCode==25||fhkScan.ErrorCode==26||fhkScan.ErrorCode==27||fhkScan.ErrorCode==41||fhkScan.ErrorCode==43){
alert('数据源错误,请检查驱动安装、设备电源或退出正在使用的应用程序')
}else if (fhkScan.ErrorCode==29){
alert('请检查设备是否正确连接并开启电源')
}else if (fhkScan.ErrorCode==30){
alert('指定了不支持的传送模式,修改 “ScanTo”属性再重试')
}else if (fhkScan.ErrorCode==31){
alert('指定了不支持的文件格式,修改 “FileType”属性再重试')
} else if (fhkScan.ErrorCode==32){
alert('请检查“FileName”属性指定的文件路径是否正确')
} else if (fhkScan.ErrorCode==34||fhkScan.ErrorCode==36){
alert('检查 TWAIN 驱动的版本')
} else if (fhkScan.ErrorCode==35){
alert('应用程序传递的窗口句柄无效,请检查窗口句柄是否正确')
}else if (fhkScan.ErrorCode==37){
alert('请确认设备是否支持 ADF 扫描,修改“PaperSupply”属性再重试')
}else if (fhkScan.ErrorCode==42){
alert('检测到取消或发生了使设备无法继续扫描的错误(如硬盘空间不足、内存不足等)')
}else if (fhkScan.ErrorCode==45){
alert('检查Z盘是否有足够的空间')
}else if (fhkScan.ErrorCode==45||fhkScan.ErrorCode==46||fhkScan.ErrorCode==47||fhkScan.ErrorCode==48||fhkScan.ErrorCode==49||fhkScan.ErrorCode==50||fhkScan.ErrorCode==51){
alert('检查“FileName”属性指定的文件路径')
} else {
alert('开始扫描出错,错误代码为 ' + fhkScan.ErrorCode)
}
fhkScan.CloseScanner(0)
}
/*CloseScanner ... 关闭扫描仪
*返回值
0 : RC_SUCCESS – 正常终止 -1 : RC_FAILURE – 错误
每当应用程序调用 OpenScanner 方法之后,都需要在结束前调用本方法;
(本方法和 OpenScanner 方法必须成对调用)
* */
let result = fhkScan.CloseScanner(0)
//扫描成功后将扫描到本地的文件上传到服务器
if (result == 0&&rtn == 0) {
this.uploadScanFile()
}
}
后台写了个java包用来将扫描到本地的文件上传到服务器端,并记录下上传的文件列表
uploadToLocalServer (fileName) {
return new Promise((resolve, reject) => {
this.$http({
url: 'http://127.0.0.1:520/localService/FTP?path=D:/scanImage/' + fileName,
method: 'GET'
}).then(res => {
if (res.data.Code != 0) {
this.fileLists = []
this.$message.error(res.data.Message)
return
}
let fileItem = res.data.Data[0]
let obj = {
fileName: fileItem.fileName,
fileUrl: fileItem.filePath,
type: 1
}
this.fileLists.push(obj)
resolve(this.fileLists)
}).catch(err => {
this.fileLists = []
console.warn(err)
})
})
},
//将上传到服务器的文件列表与当前单据关联
async uploadScanFile () {
let files = (document.getElementById('result').value.split('\n')).slice(0, -1)
let list = []
if (files.length > 0) {
files.forEach((item, index) => {
let filePath = item.replace(/\\/g, '/')
let filePathArr = filePath.split('/')
let fileName = filePathArr[filePathArr.length - 1]
list.push(this.uploadToLocalServer(fileName))
})
}
await Promise.all(list)
this.fileLists.forEach((paramsItem, paramsIndex) => {
paramsItem.uid = paramsIndex
})
this.$http({
url: this.util.getHost() + '/api/Trees/setDoc',
method: 'post',
data: {
document: this..document,
docList: this.fileLists
}
}).then(res => {
if (res.data.code != 0) {
this.$message.error(res.data.exceptionMsg)
this.fileLists=[]
return false
} else {
this.$message.success(`扫描成功`)
document.getElementById('result').value = ''
this.fileLists=[]
this.$refs['conferenceList'].updateDoc()//调用接口更新数据
}
})
},
这就完成了整个扫描过程,不过在使用过程中经常会遇到扫描仪报错(找不到数据源)的问题,需要重新启动扫描仪才可
更多推荐
已为社区贡献3条内容
所有评论(0)