綜合網上多個教程,加上自己實踐得出的方法,目前能夠兼容谷歌、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傳輸二進制流的方法,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對網站的支持!