JavaScript讀二進位檔案並用ajax傳輸二進位流的方法,javascriptajax
綜合網上多個教程,加上自己實踐得出的方法,目前能夠相容Google、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 = 1var adTypeText = 2var adSaveCreateOverWrite = 2// The trick - this is the 'old fassioned' not translation page// It lest javascript use strings to act like raw octetsvar 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 :-) - AJTforward['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' binaryBinaryStream.Type = adTypeText;BinaryStream.CharSet = '437';//Open the streamBinaryStream.Open();// Write to the streamBinaryStream.WriteText(this.Forward437(what));// Write the string to the diskBinaryStream.SaveToFile(this.path, adSaveCreateOverWrite);// Clearn upBinaryStream.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' binaryBinaryStream.Type = adTypeText;BinaryStream.CharSet = codePage;//Open the streamBinaryStream.Open();//Load the file data from disk To stream objectBinaryStream.LoadFromFile(this.path);//Open the stream And get binary 'string' from the objectvar what = BinaryStream.ReadText;// Clean upBinaryStream.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 onevar 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 onevar 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' binaryBinaryStream.Type = adTypeText;BinaryStream.CharSet = codePage;//Open the streamBinaryStream.Open();//Load the file data from disk To stream objectBinaryStream.LoadFromFile(this.path);//Open the stream And get binary 'string' from the objectvar what = BinaryStream.ReadText;// Clean upBinaryStream.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處理漢字urlxmlHttp.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告訴瀏覽器不要解析返回資料
加上這個一行後瀏覽器將不會對後台返回的資料的編碼格式進行解析,具體來講就是返回到前台的中文文本都顯示為“ ”或“口”,我估計作者這樣做是為了在前台接收後台傳來的位元據。
事實上只有Firefox的XMLHttpRequest支援sendAsBinary方法,為了在IE和Google下使用,需要給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傳輸二進位流的方法,希望對大家有所協助,如果大家有任何疑問請給我留言,小編會及時回複大家的。在此也非常感謝大家對幫客之家網站的支援!