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

207
Views
¿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 answers
Answer question

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 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!