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.

Descarga de archivo Zip a través de Axios desde el Servidor Express no está funcionando en la Aplicación React.

He implementado un backend donde los administradores pueden crear copias de seguridad. Estas copias de seguridad se recopilan en archivos zip y se almacenan en una carpeta no pública en el servidor.

Los administradores deberían ser capaces de descargar los archivos zip posteriormente. Pero esto no funciona correctamente. El archivo se descarga, pero al intentar descomprimirlo, se muestra el mensaje “”Se intentó mover el puntero del archivo antes del inicio del archivo””. El archivo zip no parece ser el problema. Si lo descomprimimos en el servidor, la descompresión funciona sin errores. Debe haber algo mal en el proceso de descarga.

La función downloadHandler que se muestra arriba se llama en la aplicación React tan pronto como un usuario hace clic en el botón de descarga de una copia de seguridad. Después de eso, el menú de descarga del navegador se abre para la descarga directa.

Implementación del servidor:

router.route(‘/backup/download’).get((req, res, next) => {
try {
res.download(path.join(backupPath, req.query.name));
} catch (err) {
next(err);
}
});

Ya he pasado horas buscando una solución, pero no importa lo que intente, no funciona. El problema es, como dije, que el archivo no se puede descomprimir después de la descarga.

Tags:  , , , ,

Answer

  1. Avatar for davy.ai

    Una posible causa del mensaje de error puede ser que el archivo no esté completamente descargado antes de que el usuario intente descomprimirlo. Para asegurarnos de que el archivo se descargue completamente antes de permitir que el usuario lo descargue, podríamos modificar la función downloadHandler de la siguiente manera:

    const downloadHandler = (params) => {
      axios({
        url: `/backup/download?name=${params.filename}`,
        method: 'GET',
        responseType: 'blob', // importante
      }).then((res) => {
        const downloadUrl = window.URL.createObjectURL(new Blob([res.data]));
        const link = document.createElement('a');
        link.href = downloadUrl;
        link.setAttribute('download', 'file.zip');
        document.body.appendChild(link);
        link.click();
        setTimeout(() => {
          window.URL.revokeObjectURL(downloadUrl); // limpiar
          link.remove();
        }, 100); // limpiar después de 100ms
      });
    };
    

    En esta versión modificada, utilizamos la biblioteca axios para hacer una solicitud GET con la opción responseType establecida en 'blob', lo que indica que queremos descargar el archivo como un objeto Blob. Luego, creamos una URL local (usando window.URL.createObjectURL()) para este Blob y la usamos para establecer el atributo href de un nuevo elemento anchor, como antes. También agregamos un método setTimeout para revocar la URL local y eliminar el elemento anchor después de 100 ms para limpiar cualquier fuga de memoria.

    En el lado del servidor, no necesitamos hacer nada, ya que el método res.download() se encarga de enviar todo el archivo al cliente antes de cerrar el flujo.

    Con esta modificación, el archivo debería estar completamente descargado antes de que el usuario tenga la oportunidad de descomprimirlo, lo que debería eliminar cualquier problema de puntero de archivo.

Comments are closed.