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 相关文章推荐
用javascript实现计算两个日期的间隔天数
Aug 14 Javascript
JQuery 浮动导航栏实现代码
Aug 27 Javascript
基于JQuery的asp.net树实现代码
Nov 30 Javascript
JavaScript调用堆栈及setTimeout使用方法深入剖析
Feb 16 Javascript
jQuery中noconflict函数的实现原理分解
Feb 03 Javascript
jQuery实现新消息在网页标题闪烁提示
Jun 23 Javascript
JavaScript函数节流概念与用法实例详解
Jun 20 Javascript
浅谈javascript控制HTML5的全屏操控,浏览器兼容的问题
Oct 10 Javascript
jQuery插件版本冲突的处理方法分析
Jan 16 Javascript
Vue父组件监听子组件生命周期
Sep 03 Javascript
在vue中axios设置timeout超时的操作
Sep 04 Javascript
解决vue-pdf查看pdf文件及打印乱码的问题
Nov 04 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
使用NetBeans + Xdebug调试PHP程序的方法
2011/04/12 PHP
PHP 日,周,月点击排行统计
2012/01/11 PHP
php curl 伪造IP来源的实例代码
2012/11/01 PHP
php判断两个日期之间相差多少个月份的方法
2015/06/18 PHP
Yii2创建多界面主题(Theme)的方法
2016/10/08 PHP
php批量删除操作代码分享
2017/02/26 PHP
Windows平台实现PHP连接SQL Server2008的方法
2017/07/26 PHP
PHP使用函数用法详解
2018/09/30 PHP
jquery 输入框数字限制插件
2009/11/10 Javascript
Document对象内容集合(比较全)
2010/09/06 Javascript
浅谈jQuery的offset()方法及示例分享
2015/07/17 Javascript
直接拿来用的15个jQuery代码片段
2015/09/23 Javascript
CSS或者JS实现鼠标悬停显示另一元素
2016/01/22 Javascript
Nodejs获取网络数据并生成Excel表格
2020/03/31 NodeJs
Angularjs之filter过滤器(推荐)
2016/11/27 Javascript
JavaScript中校验银行卡号的实现代码
2016/12/19 Javascript
微信小程序 新建登录页并实现tabBar隐藏
2017/06/13 Javascript
Node调用Java的示例代码
2017/09/20 Javascript
Vue + Vue-router 同名路由切换数据不更新的方法
2017/11/20 Javascript
基于Node的Axure文件在线预览的实现代码
2019/08/28 Javascript
[17:45]DOTA2 HEROES教学视频教你分分钟做大人-军团指挥官
2014/06/11 DOTA
python保存文件方法小结
2018/07/27 Python
python3使用matplotlib绘制条形图
2020/03/25 Python
Python中and和or如何使用
2020/05/28 Python
浅谈Python中的模块
2020/06/10 Python
Python 如何在字符串中插入变量
2020/08/01 Python
HTML5 canvas基本绘图之绘制矩形
2016/06/27 HTML / CSS
打印机墨盒:123Inkjets
2017/02/16 全球购物
匡威爱尔兰官网:Converse爱尔兰
2019/06/09 全球购物
杰夫·班克斯男士服装网上商店:Jeff Banks
2019/10/24 全球购物
简单说下OSPF的操作过程
2014/08/13 面试题
优秀技术工人先进材料
2014/02/17 职场文书
学员自我鉴定
2014/03/19 职场文书
2014年敬老院工作总结
2014/12/08 职场文书
2016年社会主义核心价值观心得体会
2016/01/21 职场文书
一行Python命令实现批量加水印
2022/04/07 Python