Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

208
Vistas
¿Cómo detectar el tamaño/tipo de archivo durante la descarga media usando axios u otro solicitante?

Tengo un raspador que busca texto en sitios de una búsqueda de Google. Sin embargo, en ocasiones, las URL para la búsqueda son archivos GRANDES sin nombres de extensión (es decir, https://myfile.com/myfile/ ).

Tengo un mecanismo de tiempo de espera en su lugar, pero cuando se agota, el archivo ya ha sobrecargado la memoria. ¿Hay alguna forma de detectar el tamaño o el tipo de archivo mientras se descarga ?

Aquí está mi función de solicitud:

 const getHtml = async (url, { timeout = 10000, ...opts } = {}) => { const CancelToken = axios.CancelToken const source = CancelToken.source() try { const timeoutId = setTimeout(() => source.cancel('Request cancelled due to timeout'), timeout) let site = await axios.get(url, { headers: { 'user-agent': userAgent().toString(), connection: 'keep-alive', // self note: Isn't this prohibited on http/2? }, cancelToken: source.token, ...opts, }) clearTimeout(timeoutId) return site.data } catch (err) { throw err } }

PD : He visto preguntas similares, pero ninguna tenía una respuesta que pudiera aplicarse.

about 4 years ago · Juan Pablo Isaza
1 Respuestas
Responde la pregunta

0

Ok, esto no es tan fácil de resolver como cabría esperar. Idealmente, los encabezados http 'Content-length' y 'Content-type' existen para que el usuario pueda saber qué debe esperar, pero estos no son encabezados obligatorios. Sin embargo, a menudo son inexactos o faltan.

La solución que encontré para este problema, que parece ser muy confiable, implica dos cosas:

  1. Hacer la solicitud como un Stream
  2. Leer la firma del archivo que tiene el primer byte de muchos archivos (probablemente debido a ISO 8859-1, que enumera estas firmas); En realidad, estos se conocen comúnmente como números mágicos/bytes .

Una excelente manera de usar estas dos cosas es transmitir la respuesta y leer los primeros bytes para verificar la firma del archivo; Una vez que sepa si el archivo está en el formato que admite/desea, puede procesarlo como lo haría normalmente o cancelar la solicitud antes de leer la siguiente parte de la transmisión, lo que debería evitar la sobrecarga de su sistema (y que también puede usar para medir el tamaño del archivo con mayor precisión, lo cual muestro en el siguiente fragmento)

Así es como implementé la solución mencionada anteriormente:

 const getHtml = async (url, { timeout = 10000, ...opts } = {}) => { const CancelToken = axios.CancelToken const source = CancelToken.source() try { const timeoutId = setTimeout(() => source.cancel('Request cancelled due to timeout'), timeout) const res = await axios.get(url, { headers: { connection: 'keep-alive', }, cancelToken: source.token, // Use stream mode so we can read the first chunk before getting the rest(1.6kB/chunk(highWatermark)) responseType: 'stream', ...opts, }) const stream = res.data; let firstChunk = true let size = 0 // Not to be confused with arrayBuffer(the object) ;) const bufferArray = [] // Async iterator syntax for consuming the stream. Iterating over a stream will consume it fully, but returning or breaking the loop in any way will destroy it for await (const chunk of stream) { if (firstChunk) { firstChunk = false // Only check the first 100(relevant, spaces excl.) chars of the chunk for html. This would possibly only fail in a raw text file which contains the word html at the very top(very unlikely and even then, wouldn't break anything) const stringChunk = String(chunk).replace(/\s+/g, '').slice(0, 100).toLowerCase() if (!stringChunk.includes('html')) return { error: `Requested URL is detected as a file. URL: ${url}\nChunk's magic 100: ${stringChunk}` }; } size += Buffer.byteLength(chunk); if (size > sizeLimit) return { error: `Requested URL is too large.\nURL: ${url}\nSize: ${size}` }; const buff = new Buffer.from(chunk) bufferArray.push(buff) } // After the stream is fully consumed, we clear the timeout and create one big buffer to convert to str and return that clearTimeout(timeoutId) return { html: Buffer.concat(bufferArray).toString() } } catch (err) { throw err } }

about 4 years ago · Juan Pablo Isaza Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda