es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Cómo detectar el tamaño / tipo de archivo mientras se está descargando utilizando axios u otro solicitante?

Tengo un rastreador que busca texto en sitios web a través de una búsqueda en Google. Sin embargo, ocasionalmente, las URL de búsqueda son archivos GRANDES sin nombres de extensión (es decir, https://myfile.com/myfile/).

Tengo un mecanismo de tiempo de espera implementado, pero para cuando expira, el archivo ya ha sobrecargado la memoria. ¿Existe alguna forma de detectar el tamaño o tipo de archivo mientras se está descargando?

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('Solicitud cancelada debido a tiempo de espera'), timeout)
    let site = await axios.get(url, {
      headers: {
        'user-agent': userAgent().toString(),
        connection: 'keep-alive', // nota personal: ¿No está prohibido en 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 aplicable.

Tags:  , , , ,

Answer

  1. Avatar for davy.ai

    Sí, es posible detectar el tamaño o tipo de archivo mientras se está descargando utilizando el encabezado Content-Length y un enfoque basado en streams. Puede modificar su función getHtml de la siguiente manera para lograr esto:

    const http = require('http');
    const https = require('https');
    
    const getHtml = async (url, { timeout = 10000, ...opts } = {}) => {
      const CancelToken = axios.CancelToken
      const source = CancelToken.source()
    
      try {
        const timeoutId = setTimeout(() => source.cancel('Solicitud cancelada debido al tiempo de espera'), timeout)
        const isHttps = url.startsWith('https');
        const client = isHttps ? https : http;
    
        let contentLength;
        let mimeType;
    
        const request = client.get(url, {
          headers: {
            'user-agent': userAgent().toString(),
            connection: 'keep-alive',
          },
          ...opts,
        }, (response) => {
          mimeType = response.headers['content-type'];
          contentLength = parseInt(response.headers['content-length'], 10);
    
          let data = '';
    
          response.on('data', (chunk) => {
            // Comparar el tamaño del archivo con un umbral aquí
            if (contentLength && contentLength > MAX_FILE_SIZE) {
              source.cancel('El tamaño del archivo supera el umbral');
              request.abort();
            }
    
            // Procesar el fragmento de datos aquí
            data += chunk;
          });
    
          response.on('end', () => {
            clearTimeout(timeoutId);
            return data;
          });
        });
    
        request.on('error', (err) => {
          throw err;
        });
    
        request.on('timeout', () => {
          source.cancel('Solicitud cancelada debido al tiempo de espera');
          request.abort();
        });
    
        return source.token.promise;
      } catch (err) {
        throw err
      }
    }
    

    Esta versión modificada de getHtml utiliza los módulos http y https incorporados de Node.js para realizar la solicitud y recibir la respuesta. El objeto de respuesta incluye los encabezados Content-Length y Content-Type, que se utilizan para detectar el tamaño y tipo de archivo, respectivamente.

    Los datos de respuesta se transmiten utilizando el evento data, lo que le permite procesar los fragmentos de datos en lugar de cargar toda la respuesta en la memoria. Puede comparar el tamaño del archivo con un umbral mientras procesa los datos y cancelar la solicitud si el tamaño del archivo supera el umbral.

    Tenga en cuenta que he agregado un valor de retorno source.token.promise al final de la función para permitir la cancelación de la solicitud utilizando source.cancel() en la función que la llama. Puede usarlo de la siguiente manera:

    const source = axios.CancelToken.source();
    
    getHtml('https://myfile.com/myfile/', { timeout: 10000, cancelToken: source.token })
      .then((data) => {
        // Maneje los datos aquí
      })
      .catch((err) => {
        if (axios.isCancel(err)) {
          console.log('Solicitud cancelada:', err.message);
        } else {
          console.error(err);
        }
      });
    

    ¡Espero que esto ayude! Avíseme si tiene alguna pregunta.

Comments are closed.