Download dei file tramite AJAX

Mattepuffo's logo
Download dei file tramite AJAX

Download dei file tramite AJAX

Update in fondo

Javascript nasce come un linguaggio lato client, e quindi non può accedere ed eseguire operazioni lato server (a meno di non usare framework specifici ovviamente, ma non è il nostro caso).

La mia necessità è quella di far scaricare agli utenti un file tramite AJAX.

Questo perchè il file, prima di essere creato, richiede un pò di elaborazione.

Usando un linguaggio lato server (nel nostro caso PHP) è possibile eseguire questa operazione.

Vediamo come iniziando proprio dalla parte server:

// CREATE IL VOSTRO FILE CON TUTTI I DATI DENTRO
header("Cache-Control: public");
header("Content-Description: File Transfer");
header("Content-Disposition: attachment; filename=file.dat");
header("Content-Type: application/octet-stream");
header("Content-Transfer-Encoding: binary");
header('Cache-Control: must-revalidate');
header('Content-Length: ' . filesize('file.dat'));
readfile('file.dat');

Ho omesso la parte di creazione del file, perchè è indipendente dal contesto.

Lo potete creare con i dati che volete, nel formato che volete ed elaborarlo come volete.

L'importante è che venga correttamente creato e che impostate gli header giusti.

A questo punto vediamo la funzione Javascript; considerate che uso jQuery per le chiamate AJAX, e quindi dovete inserirlo nella vostra pagina (o non usare jQuery se non vi piace):

function download() {
    $.ajax({
        type: "POST",
        url: "download.php",
        headers: {
            Accept: 'application/octet-stream',
        }
    }).done(function (res) {
        const a = document.createElement('a');
        a.style = 'display: none';
        document.body.appendChild(a);
        const blob = new Blob([res], {type: 'octet/stream'});
        const url = URL.createObjectURL(blob);
        a.href = url;
        a.download = 'file.dat';
        a.click();
        URL.revokeObjectURL(url);
    }).fail(function (err) {
        alert("ERRORE raber: " + err);
    });
}

In pratica eseguiamo una richiesta AJAX al file PHP sopra creato.

Leggiamo la risposta, e creiamo un link nella pagina da dove lanciamo la funzione.

L'oggetto Blob rappresenta un oggetto raw-type, e prende in carico lo stream dal server.

Molto interessante è anche URL.createObjectURL; vi consiglio di dare una sguardo al link.

Enjoy!

----

UPDATE 11 APRILE 2020

Ho visto che in effetti con i file zip possono esserci dei problemi.

Un utente mi ha indicato una soluzione che vi posto qui sotto:

$path_zip = host+pathname.substr(0, 17) + "temp_pdf/" + id + ".zip"; // COSTRUISCO IL PATH

$.ajax({
	type: "POST",
	data:{fatt:fatt_sel},
	url: "zip.php",
	headers: {
	//Accept: 'application/octet-stream',
   	Accept: 'application/zip',
	},
}).done(function (res) {
	if (selezionati>10) {
  		return;
	}

	const a = document.createElement('a');
	a.style = 'display: none';
	document.body.appendChild(a);
	//const blob = new Blob([res]);
	//const blob = new Blob([res], {type: "application/zip"});
	//const url = URL.createObjectURL(blob);
	a.href = $path_zip;
	a.click();
	window.URL.revokeObjectURL(url);
}).fail(function (err) {
	alert("ERRORE NELLA CREAZIONE DELLO ZIP : " + err);
	console.log("ERRORE NELLA CREAZIONE DELLO ZIP");
});

 


Condividi

4 Commenti

  • Michele

    stesso problema con i file .zip

    10/04/2020
  • fermat

    facendo qualche test in effetti mi ha funzionato con application/x-compressed. con application/zip anche ha dato qualche problema

    08/04/2020
  • Giuseppe

    Ciao, Riscontro lo stesso problema di Maurizio. Qualcuno ha capito il perchè?

    07/04/2020
  • Maurizio

    Ciao, grazie per la spiegazione molto chiara dell'esempio. Ho provato ad eseguire il tuo codice e funziona correttamente, ma quando sostituisco il file di download con un file .zip da scaricare, una volta completato il download mi dice che il file è corrotto. Ho provato a cambiare gli header ma non sono riuscito a lo stesso, per questo tipologia di file c'è da fare 1 operazione particolare? Grazie

    02/04/2020

Commentami!