Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

3.1K
Views
¿Cómo maneja axios blob vs arraybuffer como tipo de respuesta?

Estoy descargando un archivo zip con axios . Para un procesamiento posterior, necesito obtener los datos "sin procesar" que se han descargado. Por lo que puedo ver, en Javascript hay dos tipos para esto: Blobs y Arraybuffers. Ambos se pueden especificar como tipo de responseType en las opciones de solicitud.

En el siguiente paso, el archivo zip debe descomprimirse. Probé dos bibliotecas para esto: js-zip y adm-zip. Ambos quieren que los datos sean un ArrayBuffer. Hasta ahora todo bien, puedo convertir el blob en un búfer. Y después de esta conversión, adm-zip siempre felizmente extrae el archivo zip. Sin embargo, js-zip se queja de un archivo dañado, a menos que el zip se haya descargado con 'arraybuffer' como el tipo de responseType de axios. js-zip no funciona en un buffer tomado de un blob .

Esto fue muy confuso para mí. Pensé que tanto ArrayBuffer como Blob son esencialmente solo vistas de la memoria subyacente. Puede haber una diferencia en el rendimiento entre descargar algo como un blob y un búfer. Pero los datos resultantes deberían ser los mismos, ¿verdad?

Bueno, decidí experimentar y encontré esto:

Si especificas responseType: 'blob' , axios convierte la response.data en una cadena. Digamos que hash esta cadena y obtienes el código hash A. Luego lo conviertes en un búfer. Para esta conversión, debe especificar una codificación. Dependiendo de la codificación, obtendrá una variedad de hashes nuevos, llamémoslos B1, B2, B3, ... Al especificar 'utf8' como codificación, vuelvo al hash A original.

Entonces, supongo que al descargar datos como un 'blob' , axios los convierte implícitamente en una cadena codificada con utf8. Esto parece muy razonable.

Ahora especificas responseType: 'arraybuffer' . Axios le proporciona un búfer como response.data . Hash el búfer y obtendrá un código hash C. Este código no corresponde a ningún código en A, B1, B2, ...

Entonces, al descargar datos como un 'arraybuffer' , ¿obtiene datos completamente diferentes?

Ahora tiene sentido para mí que la biblioteca de descompresión js-zip se queje si los datos se descargan como un 'blob' . Probablemente en realidad está corrupto de alguna manera. Pero entonces, ¿cómo puede adm-zip extraerlo? Y verifiqué los datos extraídos, es correcto. Este podría ser solo el caso de este archivo zip específico, pero sin embargo me sorprende.

Aquí está el código de muestra que usé para mis experimentos:

 //typescript import syntax, this is executed in nodejs import axios from 'axios'; import * as crypto from 'crypto'; axios.get( "http://localhost:5000/folder.zip", //hosted with serve { responseType: 'blob' }) // replace this with 'arraybuffer' and response.data will be a buffer .then((response) => { console.log(typeof (response.data)); // first hash the response itself console.log(crypto.createHash('md5').update(response.data).digest('hex')); // then convert to a buffer and hash again // replace 'binary' with any valid encoding name let buffer = Buffer.from(response.data, 'binary'); console.log(crypto.createHash('md5').update(buffer).digest('hex')); //...

¿Qué crea la diferencia aquí y cómo obtengo los datos descargados "verdaderos"?

over 4 years ago · Santiago Trujillo
1 answers
Answer question

0

De los documentos de axios :

 // `responseType` indicates the type of data that the server will respond with // options are: 'arraybuffer', 'document', 'json', 'text', 'stream' // browser only: 'blob' responseType: 'json', // default

'blob' es una opción "solo para navegador".

Entonces, desde node.js, cuando configuras responseType: "blob" , en realidad se usará "json" , que supongo que se basa en "text" cuando no se han obtenido datos JSON analizables.

La obtención de datos binarios como texto es propensa a generar datos corruptos. Debido a que el texto devuelto por Body.text() y muchas otras API son USVStrings (no permiten puntos de código sustitutos no emparejados) y debido a que la respuesta se decodifica como UTF-8, algunos bytes del archivo binario no se pueden asignar a caracteres correctamente y, por lo tanto, será reemplazado por el carácter de reemplazo � (U + FFDD), sin forma de recuperar lo que eran esos datos antes: sus datos están dañados.

Aquí hay un fragmento que explica esto, usando el encabezado de un archivo .png 0x89 0x50 0x4E 0x47 como ejemplo.

 (async () => { const url = 'https://upload.wikimedia.org/wikipedia/commons/4/47/PNG_transparency_demonstration_1.png'; // fetch as binary const buffer = await fetch( url ).then(resp => resp.arrayBuffer()); const header = new Uint8Array( buffer ).slice( 0, 4 ); console.log( 'binary header', header ); // [ 137, 80, 78, 61 ] console.log( 'entity encoded', entityEncode( header ) ); // [ "U+0089", "U+0050", "U+004E", "U+0047" ] // You can read more about (U+0089) character here // https://www.fileformat.info/info/unicode/char/0089/index.htm // You can see in the left table how this character in UTF-8 needs two bytes (0xC2 0x89) // We thus can't map this character correctly in UTF-8 from the UTF-16 codePoint, // it will get discarded by the parser and converted to the replacement character // read as UTF-8 const utf8_str = await new Blob( [ header ] ).text(); console.log( 'read as UTF-8', utf8_str ); // "�PNG" // build back a binary array from that string const utf8_binary = [ ...utf8_str ].map( char => char.charCodeAt( 0 ) ); console.log( 'Which is binary', utf8_binary ); // [ 65533, 80, 78, 61 ] console.log( 'entity encoded', entityEncode( utf8_binary ) ); // [ "U+FFDD", "U+0050", "U+004E", "U+0047" ] // You can read more about character � (U+FFDD) here // https://www.fileformat.info/info/unicode/char/0fffd/index.htm // // P (U+0050), N (U+004E) and G (U+0047) characters are compatible between UTF-8 and UTF-16 // For these there is no encoding lost // (that's how base64 encoding makes it possible to send binary data as text) // now let's see what fetching as text holds const fetched_as_text = await fetch( url ).then( resp => resp.text() ); const header_as_text = fetched_as_text.slice( 0, 4 ); console.log( 'fetched as "text"', header_as_text ); // "�PNG" const as_text_binary = [ ...header_as_text ].map( char => char.charCodeAt( 0 ) ); console.log( 'Which is binary', as_text_binary ); // [ 65533, 80, 78, 61 ] console.log( 'entity encoded', entityEncode( as_text_binary ) ); // [ "U+FFDD", "U+0050", "U+004E", "U+0047" ] // It's been read as UTF-8, we lost the first byte. })(); function entityEncode( arr ) { return Array.from( arr ).map( val => 'U+' + toHex( val ) ); } function toHex( num ) { return num.toString( 16 ).padStart(4, '0').toUpperCase(); }


De forma nativa, no hay un objeto Blob en node.js, por lo que tiene sentido que Axios no lo parchee solo para que puedan devolver una respuesta que nadie más podría consumir de todos modos.

Desde un navegador, tendría exactamente las mismas respuestas:

 function fetchAs( type ) { return axios( { method: 'get', url: 'https://upload.wikimedia.org/wikipedia/commons/4/47/PNG_transparency_demonstration_1.png', responseType: type } ); } function loadImage( data, type ) { // we can all pass them to the Blob constructor directly const new_blob = new Blob( [ data ], { type: 'image/jpg' } ); // with blob: URI, the browser will try to load 'data' as-is const url = URL.createObjectURL( new_blob ); img = document.getElementById( type + '_img' ); img.src = url; return new Promise( (res, rej) => { img.onload = e => res(img); img.onerror = rej; } ); } [ 'json', // will fail 'text', // will fail 'arraybuffer', 'blob' ].forEach( type => fetchAs( type ) .then( resp => loadImage( resp.data, type ) ) .then( img => console.log( type, 'loaded' ) ) .catch( err => console.error( type, 'failed' ) ) );
 <script src="https://unpkg.com/axios/dist/axios.min.js"></script> <figure> <figcaption>json</figcaption> <img id="json_img"> </figure> <figure> <figcaption>text</figcaption> <img id="text_img"> </figure> <figure> <figcaption>arraybuffer</figcaption> <img id="arraybuffer_img"> </figure> <figure> <figcaption>blob</figcaption> <img id="blob_img"> </figure>

over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!