Saltar al contenido

Descargar y guardar datos con fetch () desde REST autenticado

Solución:

Me vi obligado a volver a esto porque acabamos de alcanzar el límite de 2 MB en Chrome. ¿Quien sabe? (Esta persona, por ejemplo: https://craignicol.wordpress.com/2016/07/19/excellent-export-and-the-chrome-url-limit/ publicó un par de meses después de mi pregunta aquí, y cuya solución implementado a continuación.)

De todos modos, lo haré ahora intento para responder a mis propias preguntas, ya que todavía no he visto una respuesta aceptable con respecto al requisito de autenticación solicitado. (Aunque, Conrado proporcionó algunos enlaces útiles para ese requisito).

En cuanto a las preguntas de: ¿Por qué tengo que hacerlo así y no hay una forma más intrínseca? Las respuestas parecen ser “solo porque” y “no”, respectivamente. No muy buenas respuestas, lo sé. Ojalá pudiera explicarlo más … pero realmente no puedo sin meter el pie en la boca en alguna parte. No soy un experto en redes y ciertamente no soy la persona adecuada para explicarlo. Simplemente es lo que es por lo que leí. Simplemente no puede falsificar una transmisión como una descarga de archivo mientras se autentica.

En cuanto a: ¿Qué me estoy perdiendo y cuál es la forma más fácil? Bueno, no hay forma más fácil. Claro, podría lanzar más bibliotecas como FileSaver.js en la base del código y dejar que me oculten parte de este código. Pero, no me gusta un conjunto de herramientas más grande de lo que realmente necesito (los estoy mirando, ridículos sitios de 50 MB). Podría lograr lo mismo que esas bibliotecas ocultando mi función download () en otro lugar e importándola. No, eso no es más fácil desde mi punto de vista. Tal vez menos trabajo para obtener una función prediseñada, pero no es más fácil en términos de la cantidad de código ejecutado para que se realice una descarga. Perdón.

Pero yo era Falta algo: eso que llevó a ese límite de 2 MB en Chrome. En ese momento, realmente no entendía cómo funcionaba este truco de datos URI que estaba usando. Encontré un código que funcionó y lo usé. Lo entiendo ahora, ahora que he tenido más tiempo para leer más en profundidad sobre esa parte del problema. En resumen, me faltaban las opciones de blob frente a la opción URI. Claro, los blobs tienen sus propias limitaciones con varios navegadores pero, dado que mis casos de uso no se habrían visto afectados por ninguno de los de 2016, la opción blob habría sido una mejor ruta desde el principio … y se siente menos hacky (y tal vez un poco “más fácil” solo por eso).

Aquí está mi solución actual que intenta guardar un blob antes de recurrir al truco de datos URI:

JS (reaccionar):

saveStreamCSV(filename, text) {
    this.setState({downloadingCSV: false})
    if(window.navigator.msSaveBlob) {
        // IE 10 and later, and Edge.
        var blobObject = new Blob([text], {type: 'text/csv'});
        window.navigator.msSaveBlob(blobObject, filename);
    } else {
        // Everthing else (except old IE).
        // Create a dummy anchor (with a download attribute) to click.
        var anchor = document.createElement('a');
        anchor.download = filename;
        if(window.URL.createObjectURL) {
            // Everything else new.
            var blobObject = new Blob([text], {type: 'text/csv'});
            anchor.href = window.URL.createObjectURL(blobObject);
        } else {
            // Fallback for older browsers (limited to 2MB on post-2010 Chrome).
            // Load up the data into the URI for "download."
            anchor.href="https://foroayuda.es/data:text/csv;charset=utf-8," + encodeURIComponent(text);
        }
        // Now, click it.
        if (document.createEvent) {
            var event = document.createEvent('MouseEvents');
            event.initEvent('click', true, true);
            anchor.dispatchEvent(event);
        }
        else {
            anchor.click();
        }
    }
}
handleDownloadClick(e) {
    this.setState({downloadingCSV: true})
    fetch(`/api/admin/studies/${this.props.study.id}/csv`
    ,   {
            headers: {
                "Authorization": "Bearer " + this.props.authAPI.getToken()
            ,   "Accept": "text/csv"
            }
        }
    )
    .then((response) => response.text())
    .then((responseText) => this.saveStreamCSV(`study${this.props.study.id}.csv`, responseText))
    .catch((error) => {
        this.setState({downloadingCSV: false})
        console.error("CSV handleDownloadClick:", error)
    })
}

Nota: Seguí esta ruta solo porque no necesito preocuparme por todos los casos de uso para los que se creó FileSaver.js (esto es solo para una función en la aplicación de administración y no para el público).

En referencia a esta respuesta, puede usar las bibliotecas FileSaver o download.js.

Ejemplo:

var saveAs = require('file-saver');

fetch('/download/urf/file', {
  headers: {
    'Content-Type': 'text/csv'
  },
  responseType: 'blob'
}).then(response => response.blob())
  .then(blob => saveAs(blob, 'test.csv'));
¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *