open example ejemplo javascript image xmlhttprequest

javascript - example - xmlhttprequest json



¿Cómo cargo los datos de imagen binarios usando Javascript y XMLHttpRequest? (3)

Estaba intentando cargar un lado del cliente de imagen 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.


Así es como lo hice.

Esta técnica se proporciona en una respuesta a otra pregunta 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. Encontré que en Firefox, al forzar el tipo mimet de la respuesta a través de overrideMimeType() , podía usar XMLHttpRequest.responseText . En IE, es diferente porque:

  • responseText en IE se 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 (¡solo 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 convertir la propiedad responseBody de IE en una cosa que se parece a responseText de FireFox, con la coerción 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 utilicé:

// 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 llame a readByte(i) para obtener el byte en la posición i-ésima en el archivo binario.

Buena suerte.

Crédito a Miskun por la lógica de conversión de VBScript.


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 más o menos lo mismo en PHP o lo que sea.


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 devolverlo al cliente.