JavaScript读二进制文件并用ajax传输二进制流的方法


Posted in Javascript onJuly 18, 2016

综合网上多个教程,加上自己实践得出的方法,目前能够兼容谷歌、IE11、IE10。

htmlbody里的内容,没什么特殊的。

<div id="dConfirm">
<p style="float: left;margin-left: 20px;margin-top: 20px">
<form action="javascript: uploadAndSubmit();" name="demoForm" id="demoForm" method="post" enctype="multipart/form-data">
<p>上传文件: <input type="file" name="file" id="str_file"/></p>
<p><input type="submit" value="上传" /></p>
</form>
</p>
</div>

读取二进制文件:

function uploadAndSubmit()
{
filename=document.getElementById("str_file").value;
var form = document.forms["demoForm"];
if(filename!="")
{
try
{
var obj = new ActiveXObject("ADODB.Stream");//这个必然是IE
}
catch(e)
{
var file = form["file"].files[0];
var reader = new FileReader();
reader.readAsBinaryString(file);//这个读法是异步的
reader.onloadend=function()
{
// 这个事件在读取结束后,无论成功或者失败都会触发
if (reader.error) {
console.log(reader.error);
} else {
uploadAndSubmit2(reader.result);
}
}
return;
}
var bf1=new BinaryFile(filename);//这个读法是同步的
uploadAndSubmit2(bf1.ReadAll());
}
}

这里要对浏览器类型做一下判断,如果不是IE则使用FileReader进行读取,如果是IE则使用activex控件读取。这里有一个坑,虽然IE11和IE10不支持FileReader对象的方法,但IE11和IE10的“typeof FileReader”并不是“undefined”,难以直接通过是否支持FileReader来区分浏览器。还要注意的是FileReader方法是异步读文件,activex是同步读文件,我一直没想明白这两条路线怎样封装在一个方法里,不知大家有没有好办法。

其中BinaryFile对象的构造方法摘自http://www.codeproject.com/Articles/17825/Reading-and-Writing-Binary-Files-Using-JScript?msg=3718403#xx3718403xx技术博客,在博客的回复中有一个改进方法据说效率更高,但因为没有看懂,所以选用了原始方法。

原始方法很长:

//使用ADODB.Stream控件时要注意ISO-8859-1和Windows-1252字符集之间的转换
function BinaryFile(name)
{
var adTypeBinary = 1
var adTypeText = 2
var adSaveCreateOverWrite = 2
// The trick - this is the 'old fassioned' not translation page
// It lest javascript use strings to act like raw octets
var codePage='437';
this.path=name;
var forward = new Array();
var backward = new Array();
// Note - for better performance I should preconvert these hex
// definitions to decimal - at some point :-) - AJT
forward['80'] = '00C7';
forward['81'] = '00FC';
forward['82'] = '00E9';
forward['83'] = '00E2';
forward['84'] = '00E4';
forward['85'] = '00E0';
forward['86'] = '00E5';
forward['87'] = '00E7';
forward['88'] = '00EA';
forward['89'] = '00EB';
forward['8A'] = '00E8';
forward['8B'] = '00EF';
forward['8C'] = '00EE';
forward['8D'] = '00EC';
forward['8E'] = '00C4';
forward['8F'] = '00C5';
forward['90'] = '00C9';
forward['91'] = '00E6';
forward['92'] = '00C6';
forward['93'] = '00F4';
forward['94'] = '00F6';
forward['95'] = '00F2';
forward['96'] = '00FB';
forward['97'] = '00F9';
forward['98'] = '00FF';
forward['99'] = '00D6';
forward['9A'] = '00DC';
forward['9B'] = '00A2';
forward['9C'] = '00A3';
forward['9D'] = '00A5';
forward['9E'] = '20A7';
forward['9F'] = '0192';
forward['A0'] = '00E1';
forward['A1'] = '00ED';
forward['A2'] = '00F3';
forward['A3'] = '00FA';
forward['A4'] = '00F1';
forward['A5'] = '00D1';
forward['A6'] = '00AA';
forward['A7'] = '00BA';
forward['A8'] = '00BF';
forward['A9'] = '2310';
forward['AA'] = '00AC';
forward['AB'] = '00BD';
forward['AC'] = '00BC';
forward['AD'] = '00A1';
forward['AE'] = '00AB';
forward['AF'] = '00BB';
forward['B0'] = '2591';
forward['B1'] = '2592';
forward['B2'] = '2593';
forward['B3'] = '2502';
forward['B4'] = '2524';
forward['B5'] = '2561';
forward['B6'] = '2562';
forward['B7'] = '2556';
forward['B8'] = '2555';
forward['B9'] = '2563';
forward['BA'] = '2551';
forward['BB'] = '2557';
forward['BC'] = '255D';
forward['BD'] = '255C';
forward['BE'] = '255B';
forward['BF'] = '2510';
forward['C0'] = '2514';
forward['C1'] = '2534';
forward['C2'] = '252C';
forward['C3'] = '251C';
forward['C4'] = '2500';
forward['C5'] = '253C';
forward['C6'] = '255E';
forward['C7'] = '255F';
forward['C8'] = '255A';
forward['C9'] = '2554';
forward['CA'] = '2569';
forward['CB'] = '2566';
forward['CC'] = '2560';
forward['CD'] = '2550';
forward['CE'] = '256C';
forward['CF'] = '2567';
forward['D0'] = '2568';
forward['D1'] = '2564';
forward['D2'] = '2565';
forward['D3'] = '2559';
forward['D4'] = '2558';
forward['D5'] = '2552';
forward['D6'] = '2553';
forward['D7'] = '256B';
forward['D8'] = '256A';
forward['D9'] = '2518';
forward['DA'] = '250C';
forward['DB'] = '2588';
forward['DC'] = '2584';
forward['DD'] = '258C';
forward['DE'] = '2590';
forward['DF'] = '2580';
forward['E0'] = '03B1';
forward['E1'] = '00DF';
forward['E2'] = '0393';
forward['E3'] = '03C0';
forward['E4'] = '03A3';
forward['E5'] = '03C3';
forward['E6'] = '00B5';
forward['E7'] = '03C4';
forward['E8'] = '03A6';
forward['E9'] = '0398';
forward['EA'] = '03A9';
forward['EB'] = '03B4';
forward['EC'] = '221E';
forward['ED'] = '03C6';
forward['EE'] = '03B5';
forward['EF'] = '2229';
forward['F0'] = '2261';
forward['F1'] = '00B1';
forward['F2'] = '2265';
forward['F3'] = '2264';
forward['F4'] = '2320';
forward['F5'] = '2321';
forward['F6'] = '00F7';
forward['F7'] = '2248';
forward['F8'] = '00B0';
forward['F9'] = '2219';
forward['FA'] = '00B7';
forward['FB'] = '221A';
forward['FC'] = '207F';
forward['FD'] = '00B2';
forward['FE'] = '25A0';
forward['FF'] = '00A0';
backward['C7'] = '80';
backward['FC'] = '81';
backward['E9'] = '82';
backward['E2'] = '83';
backward['E4'] = '84';
backward['E0'] = '85';
backward['E5'] = '86';
backward['E7'] = '87';
backward['EA'] = '88';
backward['EB'] = '89';
backward['E8'] = '8A';
backward['EF'] = '8B';
backward['EE'] = '8C';
backward['EC'] = '8D';
backward['C4'] = '8E';
backward['C5'] = '8F';
backward['C9'] = '90';
backward['E6'] = '91';
backward['C6'] = '92';
backward['F4'] = '93';
backward['F6'] = '94';
backward['F2'] = '95';
backward['FB'] = '96';
backward['F9'] = '97';
backward['FF'] = '98';
backward['D6'] = '99';
backward['DC'] = '9A';
backward['A2'] = '9B';
backward['A3'] = '9C';
backward['A5'] = '9D';
backward['20A7'] = '9E';
backward['192'] = '9F';
backward['E1'] = 'A0';
backward['ED'] = 'A1';
backward['F3'] = 'A2';
backward['FA'] = 'A3';
backward['F1'] = 'A4';
backward['D1'] = 'A5';
backward['AA'] = 'A6';
backward['BA'] = 'A7';
backward['BF'] = 'A8';
backward['2310'] = 'A9';
backward['AC'] = 'AA';
backward['BD'] = 'AB';
backward['BC'] = 'AC';
backward['A1'] = 'AD';
backward['AB'] = 'AE';
backward['BB'] = 'AF';
backward['2591'] = 'B0';
backward['2592'] = 'B1';
backward['2593'] = 'B2';
backward['2502'] = 'B3';
backward['2524'] = 'B4';
backward['2561'] = 'B5';
backward['2562'] = 'B6';
backward['2556'] = 'B7';
backward['2555'] = 'B8';
backward['2563'] = 'B9';
backward['2551'] = 'BA';
backward['2557'] = 'BB';
backward['255D'] = 'BC';
backward['255C'] = 'BD';
backward['255B'] = 'BE';
backward['2510'] = 'BF';
backward['2514'] = 'C0';
backward['2534'] = 'C1';
backward['252C'] = 'C2';
backward['251C'] = 'C3';
backward['2500'] = 'C4';
backward['253C'] = 'C5';
backward['255E'] = 'C6';
backward['255F'] = 'C7';
backward['255A'] = 'C8';
backward['2554'] = 'C9';
backward['2569'] = 'CA';
backward['2566'] = 'CB';
backward['2560'] = 'CC';
backward['2550'] = 'CD';
backward['256C'] = 'CE';
backward['2567'] = 'CF';
backward['2568'] = 'D0';
backward['2564'] = 'D1';
backward['2565'] = 'D2';
backward['2559'] = 'D3';
backward['2558'] = 'D4';
backward['2552'] = 'D5';
backward['2553'] = 'D6';
backward['256B'] = 'D7';
backward['256A'] = 'D8';
backward['2518'] = 'D9';
backward['250C'] = 'DA';
backward['2588'] = 'DB';
backward['2584'] = 'DC';
backward['258C'] = 'DD';
backward['2590'] = 'DE';
backward['2580'] = 'DF';
backward['3B1'] = 'E0';
backward['DF'] = 'E1';
backward['393'] = 'E2';
backward['3C0'] = 'E3';
backward['3A3'] = 'E4';
backward['3C3'] = 'E5';
backward['B5'] = 'E6';
backward['3C4'] = 'E7';
backward['3A6'] = 'E8';
backward['398'] = 'E9';
backward['3A9'] = 'EA';
backward['3B4'] = 'EB';
backward['221E'] = 'EC';
backward['3C6'] = 'ED';
backward['3B5'] = 'EE';
backward['2229'] = 'EF';
backward['2261'] = 'F0';
backward['B1'] = 'F1';
backward['2265'] = 'F2';
backward['2264'] = 'F3';
backward['2320'] = 'F4';
backward['2321'] = 'F5';
backward['F7'] = 'F6';
backward['2248'] = 'F7';
backward['B0'] = 'F8';
backward['2219'] = 'F9';
backward['B7'] = 'FA';
backward['221A'] = 'FB';
backward['207F'] = 'FC';
backward['B2'] = 'FD';
backward['25A0'] = 'FE';
backward['A0'] = 'FF';
var hD="0123456789ABCDEF";
this.d2h = function(d)
{
var h = hD.substr(d&15,1);
while(d>15) {d>>=4;h=hD.substr(d&15,1)+h;}
return h;
}
this.h2d = function(h)
{
return parseInt(h,16);
}
this.WriteAll = function(what)
{
//Create Stream object
//var BinaryStream = WScript.CreateObject("ADODB.Stream");
var BinaryStream = new ActiveXObject("ADODB.Stream");
//Specify stream type - we cheat and get string but 'like' binary
BinaryStream.Type = adTypeText;
BinaryStream.CharSet = '437';
//Open the stream
BinaryStream.Open();
// Write to the stream
BinaryStream.WriteText(this.Forward437(what));
// Write the string to the disk
BinaryStream.SaveToFile(this.path, adSaveCreateOverWrite);
// Clearn up
BinaryStream.Close();
}
this.ReadAll = function()
{
//Create Stream object - needs ADO 2.5 or heigher
//var BinaryStream = WScript.CreateObject("ADODB.Stream")
var BinaryStream = new ActiveXObject("ADODB.Stream");
//Specify stream type - we cheat and get string but 'like' binary
BinaryStream.Type = adTypeText;
BinaryStream.CharSet = codePage;
//Open the stream
BinaryStream.Open();
//Load the file data from disk To stream object
BinaryStream.LoadFromFile(this.path);
//Open the stream And get binary 'string' from the object
var what = BinaryStream.ReadText;
// Clean up
BinaryStream.Close();
return this.Backward437(what);
}
/* Convert a octet number to a code page 437 char code */
this.Forward437 = function(inString)
{
var encArray = new Array();
var tmp='';
var i=0;
var c=0;
var l=inString.length;
var cc;
var h;
for(;i<l;++i)
{
c++;
if(c==128)
{
encArray.push(tmp);
tmp='';
c=0;
}
cc=inString.charCodeAt(i);
if(cc<128)
{
tmp+=String.fromCharCode(cc);
}
else
{
h=this.d2h(cc);
h=forward[''+h];
tmp+=String.fromCharCode(this.h2d(h));
}
}
if(tmp!='')
{
encArray.push(tmp);
}
// this loop progressive concatonates the
// array elements entil there is only one
var ar2=new Array();
for(;encArray.length>1;)
{
var l=encArray.length;
for(var c=0;c<l;c+=2)
{
if(c+1==l)
{
ar2.push(encArray[c]);
}
else
{
ar2.push(''+encArray[c]+encArray[c+1]);
}
}
encArray=ar2;
ar2=new Array();
}
return encArray[0];
}
/* Convert a code page 437 char code to a octet number*/
this.Backward437 = function(inString)
{
var encArray = new Array();
var tmp='';
var i=0;
var c=0;
var l=inString.length;
var cc;
var h;
for(;i<l;++i)
{
c++;
if(c==128)
{
encArray.push(tmp);
tmp='';
c=0;
}
cc=inString.charCodeAt(i);
if(cc<128)
{
tmp+=String.fromCharCode(cc);
}
else
{
h=this.d2h(cc);
h=backward[''+h];
tmp+=String.fromCharCode(this.h2d(h));
}
}
if(tmp!='')
{
encArray.push(tmp);
}
// this loop progressive concatonates the
// array elements entil there is only one
var ar2=new Array();
for(;encArray.length>1;)
{
var l=encArray.length;
for(var c=0;c<l;c+=2)
{
if(c+1==l)
{
ar2.push(encArray[c]);
}
else
{
ar2.push(''+encArray[c]+encArray[c+1]);
}
}
encArray=ar2;
ar2=new Array();
}
return encArray[0];
}
}

其中主体部分是:

this.ReadAll = function()
{
//Create Stream object - needs ADO 2.5 or heigher
//var BinaryStream = WScript.CreateObject("ADODB.Stream")
var BinaryStream = new ActiveXObject("ADODB.Stream");
//Specify stream type - we cheat and get string but 'like' binary
BinaryStream.Type = adTypeText;
BinaryStream.CharSet = codePage;
//Open the stream
BinaryStream.Open();
//Load the file data from disk To stream object
BinaryStream.LoadFromFile(this.path);
//Open the stream And get binary 'string' from the object
var what = BinaryStream.ReadText;
// Clean up
BinaryStream.Close();
return this.Backward437(what);
}

这里就是使用"ADODB.Stream"控件读取文件的方法,可以看到作者使用的读取类型是adTypeText(2),是在用文本读取方式读二进制文件!而按照文档改为adTypeBinary(1)类型后则读不到任何内容,不知道是为什么。

其余部分代码则是在做编码转换工作,大体意思是读文件时要使用“ISO-8859-1”字符集,用http发送文件时则要使用“Windows-1252”字符集,这两种字符集只有极少数字符有差别,所以在读到的数据中找到有区别的部分一一转换为另一种字符集表示。

ajax发送二进制流:

function uploadAndSubmit2(BinaryContent)
{
Url = UrlHead + "Cook.ashx";
xmlHttp=new XMLHttpRequest();
xmlHttp.open("POST",Url + "?method=post&func=file_upload&fileName=" + encodeURIComponent(filename.split("\\")[filename.split("\\").length-1]));//IE处理汉字url
xmlHttp.sendAsBinary(BinaryContent);
xmlHttp.onreadystatechange = function ()
{
if (xmlHttp.readyState == 4) {
if (xmlHttp.status == 200) {
var str=xmlHttp.response;
alert(str);
xmlHttp.abort();
}
}
}
}

为了进行二进制传输这里没有使用兼容旧版本IE的“window.ActiveXObject("Msxm12.XMLHTTP")”和“window.ActiveXObject("Microsoft.XMLHTTP")”,不知大家有没有支持这两种activex控件的二进制传输方法。

在一篇教程里第六行前面有一行:

xmlHttp.overrideMimeType('text\/plain; charset=x-user-defined');//:x-user-defined告诉浏览器不要解析返回数据
加上这个一行后浏览器将不会对后台返回的数据的编码格式进行解析,具体来讲就是返回到前台的中文文本都显示为“ ”或“口”,我估计作者这样做是为了在前台接收后台传来的二进制数据。

事实上只有火狐的XMLHttpRequest支持sendAsBinary方法,为了在IE和谷歌下使用,需要给XMLHttpRequest增加一个原型方法:

//给XMLHttpRequest的原型添加二进制发送功能
XMLHttpRequest.prototype.sendAsBinary = function(datastr) {
function byteValue(x) {
return x.charCodeAt(0) & 0xff;
}
var ords = Array.prototype.map.call(datastr, byteValue);
var ui8a = new Uint8Array(ords);
this.send(ui8a.buffer);
}

这里的代码就不太懂了,其中第六行IE8不支持、第七行IE9不支持。

后台使用的是java serverlet,以下是最终调用的java类的代码:

public String FileUpload(HttpServletRequest request) throws IOException
{
request.setCharacterEncoding("UTF-8");
BufferedInputStream fileIn = new BufferedInputStream(request.getInputStream()); 
String fn = request.getParameter("fileName"); 
byte[] buf = new byte[1024]; 
File file = new File("d:/" + fn); 
BufferedOutputStream fileOut = new BufferedOutputStream(new FileOutputStream(file)); 
try
{ 
while (true) 
{ 
// 读取数据
int bytesIn = fileIn.read(buf, 0, 1024); 
System.out.println(bytesIn); 
if (bytesIn == -1) 
{ 
break; 
} 
else 
{ 
fileOut.write(buf, 0, bytesIn); 
} 
} 
fileOut.flush(); 
return("保存成功");
}
catch(Exception e)
{
return "保存失败,原因:"+e.toString();
}
finally
{ 
fileOut.close(); 
}
}

以上所述是小编给大家介绍的JavaScript读二进制文件并用ajax传输二进制流的方法,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Javascript 相关文章推荐
js压缩工具 yuicompressor 使用教程
Mar 31 Javascript
按给定几率进行随机抽取的js代码
Dec 28 Javascript
利用JavaScript检测CPU使用率自己写的
Mar 22 Javascript
Javascript实现多彩雪花从天降散落效果的方法
Feb 02 Javascript
JavaScript中神奇的call()方法
Mar 12 Javascript
jQuery实现验证表单密码一致性及正则表达式验证邮箱、手机号的方法
Dec 05 jQuery
Vue 拦截器对token过期处理方法
Jan 23 Javascript
vue element中axios下载文件(后端Python)
May 10 Javascript
vue用BMap百度地图实现即时搜索功能
Sep 26 Javascript
js中apply和call的理解与使用方法
Nov 27 Javascript
原生JS实现拖拽效果
Dec 04 Javascript
JavaScript流程控制(循环)
Dec 06 Javascript
JavaScript暂停和继续定时器的实现方法
Jul 18 #Javascript
jquery+CSS3实现3D拖拽相册效果
Jul 18 #Javascript
完美实现八种js焦点轮播图(下篇)
Apr 20 #Javascript
完美实现八种js焦点轮播图(上篇)
Jul 18 #Javascript
jQuery实现根据滚动条位置加载相应内容功能
Jul 18 #Javascript
JS HTML5拖拽上传图片预览
Jul 18 #Javascript
jQuery 操作input中radio的技巧
Jul 18 #Javascript
You might like
杏林同学录(一)
2006/10/09 PHP
54个提高PHP程序运行效率的方法
2015/07/19 PHP
ThinkPHP和UCenter接口冲突的解决方法
2016/07/25 PHP
PHP内存溢出优化代码详解
2021/02/26 PHP
Javascript 类与静态类的实现(续)
2010/04/02 Javascript
JavaScript模板入门介绍
2012/09/26 Javascript
Web跨浏览器进程通信(Web跨域)
2013/04/17 Javascript
JS中的prototype与面向对象的实例讲解
2013/05/22 Javascript
js跨域请求的5中解决方式
2015/07/02 Javascript
基于jQuery实现美观且实用的倒计时实例代码
2015/12/30 Javascript
基于javascript实现图片懒加载
2016/01/05 Javascript
JavaScript遍历Json串浏览器输出的结果不统一问题
2016/11/03 Javascript
vue2.0 datepicker使用方法
2018/02/04 Javascript
Vue页面骨架屏注入方法
2018/05/13 Javascript
使用JS实现动态时钟
2020/03/12 Javascript
jQuery实现的上拉刷新功能组件示例
2020/05/01 jQuery
javascript实现移动端红包雨页面
2020/06/23 Javascript
原生JavaScript实现拖动校验功能
2020/09/29 Javascript
[03:15]DOTA2-DPC中国联赛1月22日Recap集锦
2021/03/11 DOTA
Mac下Supervisor进程监控管理工具的安装与配置
2014/12/16 Python
用Python编写一个每天都在系统下新建一个文件夹的脚本
2015/05/04 Python
python3 使用traceback定位异常实例
2020/03/09 Python
Spring http服务远程调用实现过程解析
2020/06/11 Python
海信商城:海信电视、科龙空调、容声冰箱官方专卖
2017/02/07 全球购物
联想台湾官网:Lenovo TW
2018/05/09 全球购物
可以在一个PHP文件里面include另外一个PHP文件两次吗
2015/05/22 面试题
C++的几个面试题附答案
2016/08/03 面试题
软件部经理岗位职责范本
2014/02/25 职场文书
学习十八大坚定理想信念心得体会
2014/03/11 职场文书
司法局火灾防控方案
2014/06/05 职场文书
秋季运动会广播稿(30篇)
2014/09/13 职场文书
批评与自我批评总结
2014/10/17 职场文书
2015年服务员个人工作总结
2015/05/27 职场文书
《鲁班学艺》读后感3篇
2019/11/27 职场文书
python3 sqlite3限制条件查询的操作
2021/04/07 Python
详解CSS故障艺术
2021/05/25 HTML / CSS