2009-07-07 13 views
22

Estaba tratando de cargar una imagen del lado del cliente y base64 codifica los bytes devueltos por el servidor para pasarlo a cabo para realizar algún procesamiento. IE tiene una propiedad RequestBody del objeto XMLHttpRequest, pero parece que no puedo usarlo, y RequestText está truncado. En Firefox, RequestText está ahí, pero parece estar dañado.¿Cómo cargo los datos de imagen binarios usando Javascript y XMLHttpRequest?

+0

Después de algunos días de esfuerzo, pude hacer que esto funcionara, aunque la información en Internet para hacer tal manipulación binaria es bastante escasa. Creo que puede ser útil para otros, especialmente cuando se trata de URI de datos, así que he detallado mi trabajo aquí: [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) –

Respuesta

0

Puede hacer que el servidor devuelva texto de base64, en lugar de hacerlo en el lado del cliente de codificación.

Por ejemplo, (en ASP.NET) una solicitud a /ImageAsBase64.ashx?file=/images/myimage.png podría codificarse para leer el archivo, base64encode it y transmitirlo como respuesta.

Realmente va a ser prácticamente lo mismo en PHP o lo que sea.

+0

Desafortunadamente, en este escenario eso no funcionaría, necesitaba datos de algún software COTS y no tenía una opción base64. –

1

Si está utilizando COTS, siempre puede configurar una puerta de enlace intermedia en la que la solicitud se realiza y se transforma (base64 codificada en este caso) en algo más aceptable antes de ser devuelto al cliente.

+1

De hecho, probé esto; sin embargo, las imágenes eran específicas de la sesión del usuario y no pude falsificar el software para pensar que el servidor era parte de la misma sesión de usuario. –

12

Así es como lo hice.

Esta técnica se proporciona en una respuesta a otra pregunta de SO, pero también es relevante aquí.

No quería base64 codificar nada. Quería descargar y analizar archivos binarios en el navegador a través de Javascript, sin modificar el servidor para codificarlos especialmente. Descubrí que en Firefox, al presionar el tipo MIME de la respuesta a través de overrideMimeType(), podía usar XMLHttpRequest.responseText. En IE, es diferente porque:

  • responseText en IE trunca en el primer cero. Para las transmisiones binarias, este es un gran problema.

  • no hay XMLHttpRequest.overrideMimeType(), para forzar que IE trate flujos binarios como texto.

  • mientras que hay un XMLHttpRequest.responseBody (¡sólo IE!) Que está específicamente diseñado para ser utilizado con flujos de datos binarios, enloquecentemente esa propiedad no es utilizable desde Javascript.

Por lo tanto, la necesidad es la de convertir la propiedad de IE responseBody en algo que se parece a responseText desde Firefox, con la coacción de tipo MIME. Esto es posible usando VBScript inyectado.

Para hacerlo entre navegadores, solo tiene que empacar la lógica específica del navegador en un condicional. Esto es lo que he utilizado:

// 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); 
} 

... luego llamar readByte(i) para obtener el byte en la posición i-ésima en el archivo binario.

Buena suerte.

Credit to Miskun para la lógica de conversión de VBScript.

Cuestiones relacionadas