在项目开发时需要用到某扫描仪自带开发sdk,很坑的是只支持ie,唯一的好处是直接解决了扫描仪存到客户端的文件自动上传至服务器的功能,因为ie可以支持不安全的ActiveX,所以我为了解决扫描仪扫描至客户端的文件自动上传至服务器,使用了ActiveX。
最开始用了new ActiveXObject(“Scripting.FileSystemObject”)的getFile方法获得file对象,企图通过FormData结合ajax上传至服务器代码如下:
var fd = new FormData(),
xhr = new XMLHttpRequest(),
fso = new ActiveXObject('Scripting.FileSystemObject'),
file = fso.GetFile('C:/xxx');
fd.append('file',file);
xhr.open('POST',url);
xhr.send(fd);
结果才发现,ie没有内置的h5的对象FormData,用的话需要blablabla各种操作,太麻烦,我决定横向解决,在网上查阅相关资料后发现利用adodb.stream可以将客户端文件装载到此对象中,于是试着将前台所需信息加上文件封装到xml中,通过ajax提交至服务器,代码如下:
// 创建XML对象,组合XML文档数据
var xmlDOM = createDocument();
xmlDOM.loadXML('<?xml version="1.0" encoding="GBK" ?> <root/>');
// 创建ADODB.Stream对象
var as = new ActiveXObject("adodb.stream") , fileSize , unitSize = 1024 , read_count , node , root;
// 设置流数据类型为二进制类型
as.Type = 1; // adTypeBinary
// 打开ADODB.Stream对象
as.Open();
// 将本地文件装载到ADODB.Stream对象中
as.LoadFromFile(localPath);
// 获取文件大小(以字节为单位)
fileSize = as.Size;
// 获取文件分割数据单元的数量
read_count = parseInt((fileSize/unitSize).toString())+parseInt(((fileSize%unitSize)==0)?0:1);
/** other code... **/
// 创建XML元素节点,保存上传文件内容
for(var i=0;i<read_count;i++)
{
node = xmlDOM.createElement("uploadcontent");
// 文件内容编码方式为Base64
node.dataType = "bin.base64";
// 判断当前保存的数据节点大小,根据条件进行分类操作
if((parseInt(fileSize%unitSize)!=0)&&(i==parseInt(read_count-1))){
// 当数据包大小不是数据单元的整数倍时,读取最后剩余的小于数据单元的所有数据
node.nodeTypedValue = as.Read();
}else{
// 读取一个完整数据单元的数据
node.nodeTypedValue = as.Read(unitSize);
}
root.appendChild(node);
}
/** other code ... **/
var xhr= window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject("Microsoft.XMLHttp");
// 打开Microsoft.XMLHTP对象
xhr.open("post", targetUrl , false);
// 使用Microsoft.XMLHTP对象上传文件
xhr.send(xmlDOM);
下面是function createDocument:
function createDocument() {
var xmldom;
var versions = ['MSXML2.DOMDocument.6.0', 'MSXML2.DOMDocument.5.0','MSXML2.DOMDocument.4.0','MSXML2.DOMDocument.3.0', 'MSXML2.DOMDocument'],
i, len;
for (i = 0, len = versions.length; i < len; i++) {
try {
xmldom = new ActiveXObject(versions[i]);
if(xmldom != null)
break;
} catch (ex) {
//跳过
console.log('创建document对象失败!');
}
}
return xmldom;
}
服务器端代码:
int unit_size = 1024;
// 初始化xml文件大小(以字节为单位)
int xmlfilesize = 0;
// 初始化上传文件名称(完整文件名)
String xmlfilename = "";
// 声明文件存储字节数组
byte[] xmlfilebytes = null;
try {
// 初始化 SAX 串行xml文件解析器
SAXBuilder builder = new SAXBuilder();
Document doc = builder.build(request.getInputStream());
Element eroot = doc.getRootElement();
...
// 获取上传文件的大小
Iterator it_size = eroot.getChildren("uploadfilesize").iterator();
if (it_size.hasNext()) {
xmlfilesize = Integer.parseInt(((Element) it_size.next()).getText());
if (xmlfilesize > 0) {
int unit_count = 0;
// 为存储文件内容的字节数组分配存储空间
xmlfilebytes = new byte[xmlfilesize];
// 循环读取文件内容,并保存到字节数组中
Iterator it_content = eroot.getChildren("uploadcontent").iterator();
while (it_content.hasNext()) {
// 初始化Base64编码解码器
BASE64Decoder base64 = new BASE64Decoder();
byte[] xmlnodebytearray = base64.decodeBuffer(((Element) it_content.next()).getText());
if (xmlnodebytearray.length >= unit_size) {
// 读取一个完整数据单元的数据
System.arraycopy(xmlnodebytearray, 0, xmlfilebytes, unit_count * unit_size, unit_size);
} else {
// 读取小于一个数据单元的所有数据
System.arraycopy(xmlnodebytearray, 0, xmlfilebytes, unit_count * unit_size,
xmlfilesize % unit_size);
}
// 继续向下读取文件内容
unit_count++;
}
}
}
InputStream input = new ByteArrayInputStream(xmlfilebytes);
这样一来便获取到了数据流,然后就可以为所欲为了吧