web-dev-qa-db-fra.com

Pourquoi il n'y a aucun moyen de télécharger un fichier en utilisant une requête ajax?

Dans notre application, nous devons implémenter le scénario suivant:

  1. Une demande est envoyée par le client
  2. Le serveur gère la demande et génère le fichier.
  3. Le serveur retourne le fichier en réponse
  4. Le navigateur client affiche la boîte de dialogue contextuelle de téléchargement de fichier et permet à l'utilisateur de télécharger le fichier.

Notre application est une application basée sur ajax, il serait donc très facile et pratique pour nous d'envoyer une requête ajax (comme avec la fonction jquery.ajax()).

Mais après googilng, il s’est avéré que le téléchargement de fichier n’était possible qu’en utilisant une demande non-ajax POST (comme décrit dans ce populaire SO thread ). Nous avons donc eu besoin de mettre en oeuvre une solution plus lourde et plus complexe nécessitant la construction de la structure HTML de form avec des champs cachés imbriqués.

Quelqu'un pourrait-il expliquer avec des mots simples pourquoi les demandes ajax ne peuvent pas être utilisées pour télécharger un fichier? Quelle est la mécanique derrière cela?

46
Piotr Sobczyk

Ce n'est pas à propos d'AJAX. Vous pouvez télécharger un fichier avec AJAX, bien sûr. Toutefois, le fichier sera conservé en mémoire, c’est-à-dire que vous ne pouvez pas enregistrer le fichier sur le disque. En effet, JavaScript ne peut pas interagir avec le disque. Ce serait un grave problème de sécurité et il est bloqué dans tous les principaux navigateurs.

59
freakish

Cela peut être fait en utilisant la nouvelle fonctionnalité HTML5 appelée Blob. Il existe une bibliothèque FileSaver.js qui peut être utilisée comme wrapper par-dessus cette fonctionnalité.

3
Ilya Chernomordik

C'est la même question que je m'étais posée il y a deux jours. Il y avait un projet avec le client écrit avec ExtJS et la réalisation côté serveur était sur ASP.Net. Je dois traduire le côté serveur en Java. Il y avait une fonction pour télécharger un fichier XML, que le serveur génère après la demande Ajax du client. Nous savons tous qu'il est impossible de télécharger un fichier après une requête Ajax, il suffit de le stocker en mémoire. Mais ... dans le navigateur de l'application d'origine, affiche le dialogue habituel avec les options Ouvrir, Enregistrer et annuler le téléchargement. ASP.Net a en quelque sorte modifié le comportement standard ... Il me faut deux jours pour prouver à nouveau - il n’ya aucun moyen de télécharger un fichier à la demande de manière habituelle ... la seule exception est ASP.Net ... Voici ASP.Net. code

public static void WriteFileToResponse(byte[] fileData, string fileName)
    {
        var response = HttpContext.Current.Response;

        var returnFilename = Path.GetFileName(fileName);
        var headerValue = String.Format("attachment; filename={0}", 
            HttpUtility.UrlPathEncode(
                String.IsNullOrEmpty(returnFilename) 
                    ? "attachment" : returnFilename));
        response.AddHeader("content-disposition", headerValue);
        response.ContentType = "application/octet-stream";
        response.AddHeader("Pragma", "public");

        var utf8 = Encoding.UTF8;
        response.Charset = utf8.HeaderName;
        response.ContentEncoding = utf8;
        response.Flush();
        response.BinaryWrite(fileData);
        response.Flush();
        response.Close();
    }

Cette méthode a été appelée à partir de WebMethod, qui à son tour a été appelée à partir de ExtJS.Ajax.request. C'est la magie. Qu'est-ce qui m'arrive, j'ai fini avec servlet et iframe caché ...

1
bes67