web-dev-qa-db-fra.com

Télécharger le fichier via un appel ajax php

J'ai un bouton et onclick il appellera une fonction ajax.

Voici ma fonction ajax

function csv(){

    ajaxRequest = ajax();//ajax() is function that has all the XML HTTP Requests

    postdata = "data=" + document.getElementById("id").value;

    ajaxRequest.onreadystatechange = function(){
        var ajaxDisplay = document.getElementById('ajaxDiv');
        if(ajaxRequest.readyState == 4 && ajaxRequest.status==200){
            ajaxDisplay.innerHTML = ajaxRequest.responseText;           
        }
    }

    ajaxRequest.open("POST","csv.php",false);
    ajaxRequest.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
    ajaxRequest.send(postdata);
}

Je crée le fichier csv en fonction de l'entrée utilisateur. Une fois qu'il a été créé, je veux que le téléchargement soit rapide ou forcé (de préférence forcé). J'utilise le script suivant à la fin du fichier php pour télécharger le fichier. Si j'exécute ce script dans un fichier séparé, cela fonctionne très bien.

$fileName = 'file.csv';
$downloadFileName = 'newfile.csv';

if (file_exists($fileName)) {
    header('Content-Description: File Transfer');
    header('Content-Type: text/csv');
    header('Content-Disposition: attachment; filename='.$downloadFileName);
    ob_clean();
    flush();
    readfile($fileName);
    exit;
}
echo "done";

Mais si je l'exécute à la fin de csv.php, il affiche le contenu du fichier.csv dans la page (dans ajaxDiv) au lieu de le télécharger.

Existe-t-il un moyen de forcer le téléchargement du fichier à la fin de csv.php?

32
theking963

AJAX n'est pas destiné au téléchargement de fichiers. Ouvrez une nouvelle fenêtre avec le lien de téléchargement comme adresse ou faites document.location = ....

40
Marc B

Une solution très simple utilisant jQuery:

côté client:

$('.act_download_statement').click(function(e){
    e.preventDefault();
    form = $('#my_form');
    form.submit();
});

et côté serveur, assurez-vous de renvoyer le bon Content-Type header, pour que le navigateur sache que c'est une pièce jointe et que le téléchargement commence.

20
blink281

@joe: Merci beaucoup, c'était une bonne tête!

J'ai eu un problème un peu plus difficile: 1. envoyer une demande AJAX avec POST, pour que le serveur produise un fichier Zip 2. obtenir une réponse en retour 3 Téléchargez le fichier Zip

Voilà comment je l'ai fait (en utilisant JQuery pour gérer la AJAX):

  1. Demande de publication initiale:

    var parameters = {
         pid     : "mypid",
       "files[]": ["file1.jpg","file2.jpg","file3.jpg"]
    }


    var options = { url: "request/url",//replace with your request url type: "POST",//replace with your request type data: parameters,//see above context: document.body,//replace with your contex success: function(data){ if (data) { if (data.path) { //Create an hidden iframe, with the 'src' attribute set to the created Zip file. var dlif = $('
    <iframe /> ', {' src ': data.path}). hide (); // Ajouter l'iFrame au contexte this.append (dlif); } else if (data.error) { alert (data.error); } else { alert ('Quelque chose s'est mal passé'); } } } }; $. ajax (options);

Le "request/url" gère la création de Zip (hors sujet, donc je ne posterai pas le code complet) et retourne l'objet JSON suivant. Quelque chose comme:

 //Code to create the Zip file
 //......
 //Id of the file
 $zipid = "myzipfile.Zip"
 //Download Link - it can be prettier
 $dlink = 'http://'.$_SERVER["SERVER_NAME"].'/request/download&file='.$zipid;
 //JSON response to be handled on the client side
 $result = '{"success":1,"path":"'.$dlink.'","error":null}';
 header('Content-type: application/json;');
 echo $result;

La "demande/téléchargement" peut effectuer des vérifications de sécurité, si nécessaire, et générer le transfert de fichiers:

$fn = $_GET['file'];
if ($fn) {
  //Perform security checks
  //.....check user session/role/whatever
  $result = $_SERVER['DOCUMENT_ROOT'].'/path/to/file/'.$fn;
  if (file_exists($result)) {
    header('Content-Description: File Transfer');
    header('Content-Type: application/force-download');
    header('Content-Disposition: attachment; filename='.basename($result));
    header('Content-Transfer-Encoding: binary');
    header('Expires: 0');
    header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
    header('Pragma: public');
    header('Content-Length: ' . filesize($result));
    ob_clean();
    flush();
    readfile($result);
    @unlink($result);
  }

}
12
Dario

J'ai accompli cela avec un iframe caché. J'utilise Perl, pas php, donc je vais juste donner un concept, pas une solution de code.

Le client envoie une requête Ajax au serveur, provoquant la génération du contenu du fichier. Il est enregistré en tant que fichier temporaire sur le serveur et le nom de fichier est renvoyé au client.

Le client (javascript) reçoit le nom de fichier et définit le src iframe sur une URL qui fournira le fichier, comme:

$('iframe_dl').src="/app?download=1&filename=" + the_filename

Le serveur slurpe le fichier, le dissocie et envoie le flux au client, avec ces en-têtes:

Content-Type:'application/force-download'
Content-Disposition:'attachment; filename=the_filename'

Fonctionne comme un charme.

9
joe

Vous ne pouvez pas télécharger le fichier directement via ajax.

Vous pouvez mettre un lien sur la page avec l'URL de votre fichier (renvoyé par l'appel ajax) ou une autre façon consiste à utiliser un iframe masqué et à définir l'URL de la source de ce iframe dynamiquement. De cette façon, vous pouvez télécharger le fichier sans rafraîchir la page.

Voici le code

$.ajax({
    url : "yourURL.php",
    type : "GET",
    success : function(data) {
        $("#iframeID").attr('src', 'downloadFileURL');
    }
});
2
Naimish B. Makwana