使用JavaScript讀二進位文件並用ajax傳輸二進位流,目前能夠相容谷歌、IE11、IE10。 ...
綜合網上多個教程,加上自己實踐得出的方法,目前能夠相容谷歌、IE11、IE10。
htmlbody里的內容,沒什麼特殊的。
1 <div id="dConfirm"> 2 <p style="float: left;margin-left: 20px;margin-top: 20px"> 3 <form action="javascript: uploadAndSubmit();" name="demoForm" id="demoForm" method="post" enctype="multipart/form-data"> 4 <p>上傳文件: <input type="file" name="file" id="str_file"/></p> 5 <p><input type="submit" value="上傳" /></p> 6 </form> 7 </p> 8 </div>View Code
讀取二進位文件:
1 function uploadAndSubmit() 2 { 3 filename=document.getElementById("str_file").value; 4 var form = document.forms["demoForm"]; 5 if(filename!="") 6 { 7 try 8 { 9 var obj = new ActiveXObject("ADODB.Stream");//這個必然是IE 10 } 11 catch(e) 12 { 13 var file = form["file"].files[0]; 14 var reader = new FileReader(); 15 reader.readAsBinaryString(file);//這個讀法是非同步的 16 17 reader.onloadend=function() 18 { 19 // 這個事件在讀取結束後,無論成功或者失敗都會觸發 20 if (reader.error) { 21 console.log(reader.error); 22 } else { 23 uploadAndSubmit2(reader.result); 24 } 25 } 26 return; 27 } 28 var bf1=new BinaryFile(filename);//這個讀法是同步的 29 uploadAndSubmit2(bf1.ReadAll()); 30 } 31 }
這裡要對瀏覽器類型做一下判斷,如果不是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技術博客,在博客的回覆中有一個改進方法據說效率更高,但因為沒有看懂,所以選用了原始方法。
原始方法很長:
1 //使用ADODB.Stream控制項時要註意ISO-8859-1和Windows-1252字元集之間的轉換 2 function BinaryFile(name) 3 { 4 var adTypeBinary = 1 5 var adTypeText = 2 6 var adSaveCreateOverWrite = 2 7 // The trick - this is the 'old fassioned' not translation page 8 // It lest javascript use strings to act like raw octets 9 var codePage='437'; 10 11 this.path=name; 12 13 var forward = new Array(); 14 var backward = new Array(); 15 16 // Note - for better performance I should preconvert these hex 17 // definitions to decimal - at some point :-) - AJT 18 forward['80'] = '00C7'; 19 forward['81'] = '00FC'; 20 forward['82'] = '00E9'; 21 forward['83'] = '00E2'; 22 forward['84'] = '00E4'; 23 forward['85'] = '00E0'; 24 forward['86'] = '00E5'; 25 forward['87'] = '00E7'; 26 forward['88'] = '00EA'; 27 forward['89'] = '00EB'; 28 forward['8A'] = '00E8'; 29 forward['8B'] = '00EF'; 30 forward['8C'] = '00EE'; 31 forward['8D'] = '00EC'; 32 forward['8E'] = '00C4'; 33 forward['8F'] = '00C5'; 34 forward['90'] = '00C9'; 35 forward['91'] = '00E6'; 36 forward['92'] = '00C6'; 37 forward['93'] = '00F4'; 38 forward['94'] = '00F6'; 39 forward['95'] = '00F2'; 40 forward['96'] = '00FB'; 41 forward['97'] = '00F9'; 42 forward['98'] = '00FF'; 43 forward['99'] = '00D6'; 44 forward['9A'] = '00DC'; 45 forward['9B'] = '00A2'; 46 forward['9C'] = '00A3'; 47 forward['9D'] = '00A5'; 48 forward['9E'] = '20A7'; 49 forward['9F'] = '0192'; 50 forward['A0'] = '00E1'; 51 forward['A1'] = '00ED'; 52 forward['A2'] = '00F3'; 53 forward['A3'] = '00FA'; 54 forward['A4'] = '00F1'; 55 forward['A5'] = '00D1'; 56 forward['A6'] = '00AA'; 57 forward['A7'] = '00BA'; 58 forward['A8'] = '00BF'; 59 forward['A9'] = '2310'; 60 forward['AA'] = '00AC'; 61 forward['AB'] = '00BD'; 62 forward['AC'] = '00BC'; 63 forward['AD'] = '00A1'; 64 forward['AE'] = '00AB'; 65 forward['AF'] = '00BB'; 66 forward['B0'] = '2591'; 67 forward['B1'] = '2592'; 68 forward['B2'] = '2593'; 69 forward['B3'] = '2502'; 70 forward['B4'] = '2524'; 71 forward['B5'] = '2561'; 72 forward['B6'] = '2562'; 73 forward['B7'] = '2556'; 74 forward['B8'] = '2555'; 75 forward['B9'] = '2563'; 76 forward['BA'] = '2551'; 77 forward['BB'] = '2557'; 78 forward['BC'] = '255D'; 79 forward['BD'] = '255C'; 80 forward['BE'] = '255B'; 81 forward['BF'] = '2510'; 82 forward['C0'] = '2514'; 83 forward['C1'] = '2534'; 84 forward['C2'] = '252C'; 85 forward['C3'] = '251C'; 86 forward['C4'] = '2500'; 87 forward['C5'] = '253C'; 88 forward['C6'] = '255E'; 89 forward['C7'] = '255F'; 90 forward['C8'] = '255A'; 91 forward['C9'] = '2554'; 92 forward['CA'] = '2569'; 93 forward['CB'] = '2566'; 94 forward['CC'] = '2560'; 95 forward['CD'] = '2550'; 96 forward['CE'] = '256C'; 97 forward['CF'] = '2567'; 98 forward['D0'] = '2568'; 99 forward['D1'] = '2564'; 100 forward['D2'] = '2565'; 101 forward['D3'] = '2559'; 102 forward['D4'] = '2558'; 103 forward['D5'] = '2552'; 104 forward['D6'] = '2553'; 105 forward['D7'] = '256B'; 106 forward['D8'] = '256A'; 107 forward['D9'] = '2518'; 108 forward['DA'] = '250C'; 109 forward['DB'] = '2588'; 110 forward['DC'] = '2584'; 111 forward['DD'] = '258C'; 112 forward['DE'] = '2590'; 113 forward['DF'] = '2580'; 114 forward['E0'] = '03B1'; 115 forward['E1'] = '00DF'; 116 forward['E2'] = '0393'; 117 forward['E3'] = '03C0'; 118 forward['E4'] = '03A3'; 119 forward['E5'] = '03C3'; 120 forward['E6'] = '00B5'; 121 forward['E7'] = '03C4'; 122 forward['E8'] = '03A6'; 123 forward['E9'] = '0398'; 124 forward['EA'] = '03A9'; 125 forward['EB'] = '03B4'; 126 forward['EC'] = '221E'; 127 forward['ED'] = '03C6'; 128 forward['EE'] = '03B5'; 129 forward['EF'] = '2229'; 130 forward['F0'] = '2261'; 131 forward['F1'] = '00B1'; 132 forward['F2'] = '2265'; 133 forward['F3'] = '2264'; 134 forward['F4'] = '2320'; 135 forward['F5'] = '2321'; 136 forward['F6'] = '00F7'; 137 forward['F7'] = '2248'; 138 forward['F8'] = '00B0'; 139 forward['F9'] = '2219'; 140 forward['FA'] = '00B7'; 141 forward['FB'] = '221A'; 142 forward['FC'] = '207F'; 143 forward['FD'] = '00B2'; 144 forward['FE'] = '25A0'; 145 forward['FF'] = '00A0'; 146 backward['C7'] = '80'; 147 backward['FC'] = '81'; 148 backward['E9'] = '82'; 149 backward['E2'] = '83'; 150 backward['E4'] = '84'; 151 backward['E0'] = '85'; 152 backward['E5'] = '86'; 153 backward['E7'] = '87'; 154 backward['EA'] = '88'; 155 backward['EB'] = '89'; 156 backward['E8'] = '8A'; 157 backward['EF'] = '8B'; 158 backward['EE'] = '8C'; 159 backward['EC'] = '8D'; 160 backward['C4'] = '8E'; 161 backward['C5'] = '8F'; 162 backward['C9'] = '90'; 163 backward['E6'] = '91'; 164 backward['C6'] = '92'; 165 backward['F4'] = '93'; 166 backward['F6'] = '94'; 167 backward['F2'] = '95'; 168 backward['FB'] = '96'; 169 backward['F9'] = '97'; 170 backward['FF'] = '98'; 171 backward['D6'] = '99'; 172 backward['DC'] = '9A'; 173 backward['A2'] = '9B'; 174 backward['A3'] = '9C'; 175 backward['A5'] = '9D'; 176 backward['20A7'] = '9E'; 177 backward['192'] = '9F'; 178 backward['E1'] = 'A0'; 179 backward['ED'] = 'A1'; 180 backward['F3'] = 'A2'; 181 backward['FA'] = 'A3'; 182 backward['F1'] = 'A4'; 183 backward['D1'] = 'A5'; 184 backward['AA'] = 'A6'; 185 backward['BA'] = 'A7'; 186 backward['BF'] = 'A8'; 187 backward['2310'] = 'A9'; 188 backward['AC'] = 'AA'; 189 backward['BD'] = 'AB'; 190 backward['BC'] = 'AC'; 191 backward['A1'] = 'AD'; 192 backward['AB'] = 'AE'; 193 backward['BB'] = 'AF'; 194 backward['2591'] = 'B0'; 195 backward['2592'] = 'B1'; 196 backward['2593'] = 'B2'; 197 backward['2502'] = 'B3'; 198 backward['2524'] = 'B4'; 199 backward['2561'] = 'B5'; 200 backward['2562'] = 'B6'; 201 backward['2556'] = 'B7'; 202 backward['2555'] = 'B8'; 203 backward['2563'] = 'B9'; 204 backward['2551'] = 'BA'; 205 backward['2557'] = 'BB'; 206 backward['255D'] = 'BC'; 207 backward['255C'] = 'BD'; 208 backward['255B'] = 'BE'; 209 backward['2510'] = 'BF'; 210 backward['2514'] = 'C0'; 211 backward['2534'] = 'C1'; 212 backward['252C'] = 'C2'; 213 backward['251C'] = 'C3'; 214 backward['2500'] = 'C4'; 215 backward['253C'] = 'C5'; 216 backward['255E'] = 'C6'; 217 backward['255F'] = 'C7'; 218 backward['255A'] = 'C8'; 219 backward['2554'] = 'C9'; 220 backward['2569'] = 'CA'; 221 backward['2566'] = 'CB'; 222 backward['2560'] = 'CC'; 223 backward['2550'] = 'CD'; 224 backward['256C'] = 'CE'; 225 backward['2567'] = 'CF'; 226 backward['2568'] = 'D0'; 227 backward['2564'] = 'D1'; 228 backward['2565'] = 'D2'; 229 backward['2559'] = 'D3'; 230 backward['2558'] = 'D4'; 231 backward['2552'] = 'D5'; 232 backward['2553'] = 'D6'; 233 backward['256B'] = 'D7'; 234 backward['256A'] = 'D8'; 235 backward['2518'] = 'D9'; 236 backward['250C'] = 'DA'; 237 backward['2588'] = 'DB'; 238 backward['2584'] = 'DC'; 239 backward['258C'] = 'DD'; 240 backward['2590'] = 'DE'; 241 backward['2580'] = 'DF'; 242 backward['3B1'] = 'E0'; 243 backward['DF'] = 'E1'; 244 backward['393'] = 'E2'; 245 backward['3C0'] = 'E3'; 246 backward['3A3'] = 'E4'; 247 backward['3C3'] = 'E5'; 248 backward['B5'] = 'E6'; 249 backward['3C4'] = 'E7'; 250 backward['3A6'] = 'E8'; 251 backward['398'] = 'E9'; 252 backward['3A9'] = 'EA'; 253 backward['3B4'] = 'EB'; 254 backward['221E'] = 'EC'; 255 backward['3C6'] = 'ED'; 256 backward['3B5'] = 'EE'; 257 backward['2229'] = 'EF'; 258 backward['2261'] = 'F0'; 259 backward['B1'] = 'F1'; 260 backward['2265'] = 'F2'; 261 backward['2264'] = 'F3'; 262 backward['2320'] = 'F4'; 263 backward['2321'] = 'F5'; 264 backward['F7'] = 'F6'; 265 backward['2248'] = 'F7'; 266 backward['B0'] = 'F8'; 267 backward['2219'] = 'F9'; 268 backward['B7'] = 'FA'; 269 backward['221A'] = 'FB'; 270 backward['207F'] = 'FC'; 271 backward['B2'] = 'FD'; 272 backward['25A0'] = 'FE'; 273 backward['A0'] = 'FF'; 274 275 var hD="0123456789ABCDEF"; 276 this.d2h = function(d) 277 { 278 var h = hD.substr(d&15,1); 279 while(d>15) {d>>=4;h=hD.substr(d&15,1)+h;} 280 return h; 281 } 282 283 this.h2d = function(h) 284 { 285 return parseInt(h,16); 286 } 287 288 this.WriteAll = function(what) 289 { 290 //Create Stream object 291 //var BinaryStream = WScript.CreateObject("ADODB.Stream"); 292 var BinaryStream = new ActiveXObject("ADODB.Stream"); 293 //Specify stream type - we cheat and get string but 'like' binary 294 BinaryStream.Type = adTypeText; 295 BinaryStream.CharSet = '437'; 296 //Open the stream 297 BinaryStream.Open(); 298 // Write to the stream 299 BinaryStream.WriteText(this.Forward437(what)); 300 // Write the string to the disk 301 BinaryStream.SaveToFile(this.path, adSaveCreateOverWrite); 302 303 // Clearn up 304 BinaryStream.Close(); 305 } 306 307 this.ReadAll = function() 308 { 309 //Create Stream object - needs ADO 2.5 or heigher 310 //var BinaryStream = WScript.CreateObject("ADODB.Stream") 311 var BinaryStream = new ActiveXObject("ADODB.Stream"); 312 //Specify stream type - we cheat and get string but 'like' binary 313 BinaryStream.Type = adTypeText; 314 BinaryStream.CharSet = codePage; 315 //Open the stream 316 BinaryStream.Open(); 317 //Load the file data from disk To stream object 318 BinaryStream.LoadFromFile(this.path); 319 //Open the stream And get binary 'string' from the object 320 var what = BinaryStream.ReadText; 321 // Clean up 322 BinaryStream.Close(); 323 return this.Backward437(what); 324 } 325 326 /* Convert a octet number to a code page 437 char code */ 327 this.Forward437 = function(inString) 328 { 329 var encArray = new Array(); 330 var tmp=''; 331 var i=0; 332 var c=0; 333 var l=inString.length; 334 var cc; 335 var h; 336 for(;i<l;++i) 337 { 338 c++; 339 if(c==128) 340 { 341 encArray.push(tmp); 342 tmp=''; 343 c=0; 344 } 345 cc=inString.charCodeAt(i); 346 if(cc<128) 347 { 348 tmp+=String.fromCharCode(cc); 349 } 350 else 351 { 352 h=this.d2h(cc); 353 h=forward[''+h]; 354 tmp+=String.fromCharCode(this.h2d(h)); 355 } 356 } 357 if(tmp!='') 358 { 359 encArray.push(tmp); 360 } 361 362 // this loop progressive concatonates the 363 // array elements entil there is only one 364 var ar2=new Array(); 365 for(;encArray.length>1;) 366 { 367 var l=encArray.length; 368 for(var c=0;c<l;c+=2) 369 { 370 if(c+1==l) 371 { 372 ar2.push(encArray[c]); 373 } 374 else 375 { 376 ar2.push(''+encArray[c]+encArray[c+1]); 377 } 378 } 379 encArray=ar2; 380 ar2=new Array(); 381 } 382 return encArray[0]; 383 } 384 /* Convert a code page 437 char code to a octet number*/ 385 this.Backward437 = function(inString) 386 { 387 var encArray = new Array(); 388 var tmp=''; 389 var i=0; 390 var c=0; 391 var l=inString.length; 392 var cc; 393 var h; 394 for(;i<l;++i) 395 { 396 c++; 397 if(c==128) 398 { 399 encArray.push(tmp); 400 tmp=''; 401 c=0; 402 } 403 cc=inString.charCodeAt(i); 404 if(cc<128) 405 { 406 tmp+=String.fromCharCode(cc); 407 } 408 else 409 { 410 h=this.d2h(cc); 411 h=backward[''+h]; 412 tmp+=String.fromCharCode(this.h2d(h)); 413 } 414 } 415 if(tmp!='') 416 { 417 encArray.push(tmp); 418 } 419 420 // this loop progressive concatonates the 421 // array elements entil there is only one 422 var ar2=new Array(); 423 for(;encArray.length>1;) 424 { 425 var l=encArray.length; 426 for(var c=0;c<l;c+=2) 427 { 428 if(c+1==l) 429 { 430 ar2.push(encArray[c]); 431 } 432 else 433 { 434 ar2.push(''+encArray[c]+encArray[c+1]); 435 } 436 } 437 encArray=ar2; 438 ar2=new Array(); 439 } 440 return encArray[0]; 441 } 442 }View Code
其中主體部分是:
1 this.ReadAll = function() 2 { 3 //Create Stream object - needs ADO 2.5 or heigher 4 //var BinaryStream = WScript.CreateObject("ADODB.Stream") 5 var BinaryStream = new ActiveXObject("ADODB.Stream"); 6 //Specify stream type - we cheat and get string but 'like' binary 7 BinaryStream.Type = adTypeText; 8 BinaryStream.CharSet = codePage; 9 //Open the stream 10 BinaryStream.Open(); 11 //Load the file data from disk To stream object 12 BinaryStream.LoadFromFile(this.path); 13 //Open the stream And get binary 'string' from the object 14 var what = BinaryStream.ReadText; 15 // Clean up 16 BinaryStream.Close(); 17 return this.Backward437(what); 18 }
這裡就是使用"ADODB.Stream"控制項讀取文件的方法,可以看到作者使用的讀取類型是adTypeText(2),是在用文本讀取方式讀二進位文件!而按照文檔改為adTypeBinary(1)類型後則讀不到任何內容,不知道是為什麼。
其餘部分代碼則是在做編碼轉換工作,大體意思是讀文件時要使用“ISO-8859-1”字元集,用http發送文件時則要使用“Windows-1252”字元集,這兩種字元集只有極少數字元有差別,所以在讀到的數據中找到有區別的部分一一轉換為另一種字元集表示。
ajax發送二進位流:
1 function uploadAndSubmit2(BinaryContent) 2 { 3 Url = UrlHead + "Cook.ashx"; 4 xmlHttp=new XMLHttpRequest(); 5 xmlHttp.open("POST",Url + "?method=post&func=file_upload&fileName=" + encodeURIComponent(filename.split("\\")[filename.split("\\").length-1]));//IE處理漢字url 6 xmlHttp.sendAsBinary(BinaryContent); 7 xmlHttp.onreadystatechange = function () 8 { 9 if (xmlHttp.readyState == 4) { 10 if (xmlHttp.status == 200) { 11 var str=xmlHttp.response; 12 alert(str);