2009-07-07 4 views
22

Ich habe versucht, eine Image-Client-Seite zu laden und base64 die vom Server zurückgegebenen Bytes zu codieren, um sie zur Durchführung einiger Verarbeitungen zu übergeben. IE hat eine RequestBody-Eigenschaft des XMLHttpRequest-Objekts, aber ich kann es anscheinend nicht verwenden, und RequestText wird abgeschnitten. In Firefox ist RequestText vorhanden, scheint jedoch beschädigt zu sein.Wie lade ich binäre Bilddaten mit Javascript und XMLHttpRequest?

+0

Nach ein paar Tagen Aufwand konnte ich diese Arbeit machen, obwohl Informationen im Internet für solche binäre Manipulation ist ziemlich knapp. Ich denke, dass es für andere nützlich sein kann, insbesondere wenn es um Daten-URIs geht. Deshalb habe ich meine Arbeit hier ausführlich beschrieben: [http://emilsblog.lerch.org/2009/07/javascript-hacks-using-xhr-to- load.html] (http: //emilsblog.lerch.org/2009/07/javascript-hacks-using-xhr-to-load.html) –

Antwort

0

Sie könnten den Server base64-Text zurückgeben lassen, anstatt die Clientseite für die Codierung zu verwenden.

Zum Beispiel (in ASP.NET) könnte eine Anfrage an /ImageAsBase64.ashx?file=/images/myimage.png codiert werden, um die Datei zu lesen, base64encode und als Antwort darauf zu streamen.

Es wird wirklich in PHP oder was auch immer dasselbe sein.

+0

Leider in diesem Szenario würde das nicht funktionieren - Ich benötigte Daten von einigen COTS-Software, und es hatte keine Base64-Option. –

1

Wenn Sie COTS verwenden, können Sie immer ein intermediäres Gateway einrichten, in dem die Anforderung erstellt und (in diesem Fall base64-codiert) in etwas schmackhafteres umgewandelt wird, bevor sie an den Client zurückgegeben wird.

+1

Ich habe das tatsächlich versucht; Die Bilder waren jedoch spezifisch für die Benutzersitzung und ich konnte die Software nicht fälschen, um zu glauben, dass der Server Teil derselben Benutzersitzung war. –

12

Hier ist, wie ich es gemacht habe.

Diese Technik wird in einer Antwort auf eine andere SO-Frage bereitgestellt, ist aber auch hier relevant.

Ich wollte nicht Base64 etwas kodieren. Ich wollte Binärdateien im Browser über Javascript herunterladen und parsen, ohne den Server zu modifizieren, um sie speziell zu verschlüsseln. Ich fand heraus, dass ich in Firefox, indem ich den Mimetyp der Antwort über overrideMimeType() erzwingen, könnte ich XMLHttpRequest.responseText verwenden. Auf IE, es ist anders, weil:

  • responseText auf IE beim ersten Null abschneidet. Bei binären Streams ist dies ein großes Problem.

  • gibt es keine XMLHttpRequest.overrideMimeType(), um IE zu zwingen, binäre Ströme als Text zu behandeln.

  • während es eine XMLHttpRequest.responseBody (IE nur!), Die spezifisch mit binären Datenströmen verwendet werden soll, aufreizend, dass Eigentum nicht benutzbar von Javascript ist.

Daher ist die Notwendigkeit IE responseBody Eigenschaft in eine Sache zu konvertieren, wie responseText von FireFox, mit dem MIME-Typ Zwang aussieht. Dies ist mit injiziertem VBScript möglich.

Um es browserübergreifend zu machen, müssen Sie nur die browserspezifische Logik in eine Bedingung einpacken. Dies ist, was ich verwendet:

// one-time code 
if(/msie/i.test(navigator.userAgent) && !/opera/i.test(navigator.userAgent)) { 
    var IEBinaryToArray_ByteStr_Script = 
    "<!-- IEBinaryToArray_ByteStr -->\r\n"+ 
    "<script type='text/vbscript'>\r\n"+ 
    "Function IEBinaryToArray_ByteStr(Binary)\r\n"+ 
    " IEBinaryToArray_ByteStr = CStr(Binary)\r\n"+ 
    "End Function\r\n"+ 
    "Function IEBinaryToArray_ByteStr_Last(Binary)\r\n"+ 
    " Dim lastIndex\r\n"+ 
    " lastIndex = LenB(Binary)\r\n"+ 
    " if lastIndex mod 2 Then\r\n"+ 
    "  IEBinaryToArray_ByteStr_Last = Chr(AscB(MidB(Binary, lastIndex, 1)))\r\n"+ 
    " Else\r\n"+ 
    "  IEBinaryToArray_ByteStr_Last = "+'""'+"\r\n"+ 
    " End If\r\n"+ 
    "End Function\r\n"+ 
    "</script>\r\n"; 

    // inject VBScript 
    document.write(IEBinaryToArray_ByteStr_Script); 
} 


// each time you make a request for a binary resource: 
var req = (function() { 
    if (window.XMLHttpRequest) { 
     return new window.XMLHttpRequest(); 
    } 
    else { 
     try { 
      return new ActiveXObject("MSXML2.XMLHTTP"); 
     } 
     catch(ex) { 
      return null; 
     } 
    } 
})(); 

var fileContents = ""; 
var filesize = -1; 
var readByteAt = function(i){ 
    return fileContents.charCodeAt(i) & 0xff; 
}; 

req.open("GET", url, true); 

if(/msie/i.test(navigator.userAgent) && !/opera/i.test(navigator.userAgent)) { 
    // IE-specific logic here 
    // helper to convert from responseBody to a "responseText" like thing 
    var convertResponseBodyToText = function (binary) { 
     var byteMapping = {}; 
     for (var i = 0; i < 256; i++) { 
      for (var j = 0; j < 256; j++) { 
       byteMapping[ String.fromCharCode(i + j * 256) ] = 
        String.fromCharCode(i) + String.fromCharCode(j); 
      } 
     } 
     var rawBytes = IEBinaryToArray_ByteStr(binary); 
     var lastChr = IEBinaryToArray_ByteStr_Last(binary); 
     return rawBytes.replace(/[\s\S]/g, 
           function(match) { return byteMapping[match]; }) + lastChr; 
    }; 

    req.setRequestHeader("Accept-Charset", "x-user-defined"); 
    req.onreadystatechange = function(event){ 
     if (req.readyState == 4) { 
      if (req.status == 200) { 
       fileContents = convertResponseBodyToText(req.responseBody); 
       fileSize = fileContents.length-1; 
       // invoke a callback here, if you like... 
      } 
      else{ 
       alert("download failed, status " + req.status); 
      } 
     } 
    }; 
    req.send(); 

} else { 
    // ff/Gecko/Webkit specific stuff here 
    req.onreadystatechange = function(aEvt) { 
     if (req.readyState == 4) { // completed 
      if(req.status == 200){ // status == OK 
       fileContents = binStream.req.responseText; 
       filesize = fileContents.length; 
       // invoke a callback here, if you like... 
      } 
      else { 
       alert("download failed, status " + req.status); 
      } 
     } 
    }; 
    // coerce response type 
    req.overrideMimeType('text/plain; charset=x-user-defined'); 
    req.send(null); 
} 

... dann readByte(i) rufen Sie das Byte an der ith Position in der Binärdatei zu erhalten.

Viel Glück.

Credit to Miskun für die VBScript-Konvertierungslogik.

Verwandte Themen