JavaScript读二进制文件并用ajax传输二进制流的方法
综合网上多个教程,加上自己实践得出的方法,目前能够兼容谷歌、IE11、IE10。
htmlbody里的内容,没什么特殊的。
<divid="dConfirm"> <pstyle="float:left;margin-left:20px;margin-top:20px"> <formaction="javascript:uploadAndSubmit();"name="demoForm"id="demoForm"method="post"enctype="multipart/form-data"> <p>上传文件:<inputtype="file"name="file"id="str_file"/></p> <p><inputtype="submit"value="上传"/></p> </form> </p> </div>
读取二进制文件:
functionuploadAndSubmit() { filename=document.getElementById("str_file").value; varform=document.forms["demoForm"]; if(filename!="") { try { varobj=newActiveXObject("ADODB.Stream");//这个必然是IE } catch(e) { varfile=form["file"].files[0]; varreader=newFileReader(); reader.readAsBinaryString(file);//这个读法是异步的 reader.onloadend=function() { //这个事件在读取结束后,无论成功或者失败都会触发 if(reader.error){ console.log(reader.error); }else{ uploadAndSubmit2(reader.result); } } return; } varbf1=newBinaryFile(filename);//这个读法是同步的 uploadAndSubmit2(bf1.ReadAll()); } }
这里要对浏览器类型做一下判断,如果不是IE则使用FileReader进行读取,如果是IE则使用activex控件读取。这里有一个坑,虽然IE11和IE10不支持FileReader对象的方法,但IE11和IE10的“typeofFileReader”并不是“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字符集之间的转换 functionBinaryFile(name) { varadTypeBinary=1 varadTypeText=2 varadSaveCreateOverWrite=2 //Thetrick-thisisthe'oldfassioned'nottranslationpage //Itlestjavascriptusestringstoactlikerawoctets varcodePage='437'; this.path=name; varforward=newArray(); varbackward=newArray(); //Note-forbetterperformanceIshouldpreconvertthesehex //definitionstodecimal-atsomepoint:-)-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'; varhD="0123456789ABCDEF"; this.d2h=function(d) { varh=hD.substr(d&15,1); while(d>15){d>>=4;h=hD.substr(d&15,1)+h;} returnh; } this.h2d=function(h) { returnparseInt(h,16); } this.WriteAll=function(what) { //CreateStreamobject //varBinaryStream=WScript.CreateObject("ADODB.Stream"); varBinaryStream=newActiveXObject("ADODB.Stream"); //Specifystreamtype-wecheatandgetstringbut'like'binary BinaryStream.Type=adTypeText; BinaryStream.CharSet='437'; //Openthestream BinaryStream.Open(); //Writetothestream BinaryStream.WriteText(this.Forward437(what)); //Writethestringtothedisk BinaryStream.SaveToFile(this.path,adSaveCreateOverWrite); //Clearnup BinaryStream.Close(); } this.ReadAll=function() { //CreateStreamobject-needsADO2.5orheigher //varBinaryStream=WScript.CreateObject("ADODB.Stream") varBinaryStream=newActiveXObject("ADODB.Stream"); //Specifystreamtype-wecheatandgetstringbut'like'binary BinaryStream.Type=adTypeText; BinaryStream.CharSet=codePage; //Openthestream BinaryStream.Open(); //LoadthefiledatafromdiskTostreamobject BinaryStream.LoadFromFile(this.path); //OpenthestreamAndgetbinary'string'fromtheobject varwhat=BinaryStream.ReadText; //Cleanup BinaryStream.Close(); returnthis.Backward437(what); } /*Convertaoctetnumbertoacodepage437charcode*/ this.Forward437=function(inString) { varencArray=newArray(); vartmp=''; vari=0; varc=0; varl=inString.length; varcc; varh; 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); } //thisloopprogressiveconcatonatesthe //arrayelementsentilthereisonlyone varar2=newArray(); for(;encArray.length>1;) { varl=encArray.length; for(varc=0;c<l;c+=2) { if(c+1==l) { ar2.push(encArray[c]); } else { ar2.push(''+encArray[c]+encArray[c+1]); } } encArray=ar2; ar2=newArray(); } returnencArray[0]; } /*Convertacodepage437charcodetoaoctetnumber*/ this.Backward437=function(inString) { varencArray=newArray(); vartmp=''; vari=0; varc=0; varl=inString.length; varcc; varh; 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); } //thisloopprogressiveconcatonatesthe //arrayelementsentilthereisonlyone varar2=newArray(); for(;encArray.length>1;) { varl=encArray.length; for(varc=0;c<l;c+=2) { if(c+1==l) { ar2.push(encArray[c]); } else { ar2.push(''+encArray[c]+encArray[c+1]); } } encArray=ar2; ar2=newArray(); } returnencArray[0]; } }
其中主体部分是:
this.ReadAll=function() { //CreateStreamobject-needsADO2.5orheigher //varBinaryStream=WScript.CreateObject("ADODB.Stream") varBinaryStream=newActiveXObject("ADODB.Stream"); //Specifystreamtype-wecheatandgetstringbut'like'binary BinaryStream.Type=adTypeText; BinaryStream.CharSet=codePage; //Openthestream BinaryStream.Open(); //LoadthefiledatafromdiskTostreamobject BinaryStream.LoadFromFile(this.path); //OpenthestreamAndgetbinary'string'fromtheobject varwhat=BinaryStream.ReadText; //Cleanup BinaryStream.Close(); returnthis.Backward437(what); }
这里就是使用"ADODB.Stream"控件读取文件的方法,可以看到作者使用的读取类型是adTypeText(2),是在用文本读取方式读二进制文件!而按照文档改为adTypeBinary(1)类型后则读不到任何内容,不知道是为什么。
其余部分代码则是在做编码转换工作,大体意思是读文件时要使用“ISO-8859-1”字符集,用http发送文件时则要使用“Windows-1252”字符集,这两种字符集只有极少数字符有差别,所以在读到的数据中找到有区别的部分一一转换为另一种字符集表示。
ajax发送二进制流:
functionuploadAndSubmit2(BinaryContent) { Url=UrlHead+"Cook.ashx"; xmlHttp=newXMLHttpRequest(); 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){ varstr=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){ functionbyteValue(x){ returnx.charCodeAt(0)&0xff; } varords=Array.prototype.map.call(datastr,byteValue); varui8a=newUint8Array(ords); this.send(ui8a.buffer); }
这里的代码就不太懂了,其中第六行IE8不支持、第七行IE9不支持。
后台使用的是javaserverlet,以下是最终调用的java类的代码:
publicStringFileUpload(HttpServletRequestrequest)throwsIOException { request.setCharacterEncoding("UTF-8"); BufferedInputStreamfileIn=newBufferedInputStream(request.getInputStream()); Stringfn=request.getParameter("fileName"); byte[]buf=newbyte[1024]; Filefile=newFile("d:/"+fn); BufferedOutputStreamfileOut=newBufferedOutputStream(newFileOutputStream(file)); try { while(true) { //读取数据 intbytesIn=fileIn.read(buf,0,1024); System.out.println(bytesIn); if(bytesIn==-1) { break; } else { fileOut.write(buf,0,bytesIn); } } fileOut.flush(); return("保存成功"); } catch(Exceptione) { return"保存失败,原因:"+e.toString(); } finally { fileOut.close(); } }
以上所述是小编给大家介绍的JavaScript读二进制文件并用ajax传输二进制流的方法,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对毛票票网站的支持!