J'ai une webapp d'une seule page basée sur jquery. Il communique avec un service Web RESTful via des appels AJAX.
J'essaie d'accomplir ce qui suit:
- Soumettez un POST contenant des données JSON à une URL REST.
- Si la demande spécifie une réponse JSON, alors JSON est renvoyé.
- Si la demande spécifie une réponse PDF / XLS / etc, un fichier binaire téléchargeable est renvoyé.
J'ai 1 & 2 travaillant maintenant, et l'application client jquery affiche les données renvoyées dans la page Web en créant des éléments DOM basés sur les données JSON. J'ai également le n ° 3 qui fonctionne du point de vue du service Web, ce qui signifie qu'il créera et renverra un fichier binaire s'il reçoit les paramètres JSON corrects. Mais je ne suis pas sûr de la meilleure façon de traiter # 3 dans le code javascript du client.
Est-il possible de récupérer un fichier téléchargeable à partir d'un appel ajax comme celui-ci? Comment faire pour que le navigateur télécharge et enregistre le fichier?
$.ajax({
type: "POST",
url: "/services/test",
contentType: "application/json",
data: JSON.stringify({category: 42, sort: 3, type: "pdf"}),
dataType: "json",
success: function(json, status){
if (status != "success") {
log("Error loading data");
return;
}
log("Data loaded!");
},
error: function(result, status, err) {
log("Error loading data");
return;
}
});
Le serveur répond avec les en-têtes suivants:
Content-Disposition:attachment; filename=export-1282022272283.pdf
Content-Length:5120
Content-Type:application/pdf
Server:Jetty(6.1.11)
Une autre idée est de générer le PDF et de le stocker sur le serveur et de renvoyer le JSON qui inclut une URL vers le fichier. Ensuite, lancez un autre appel dans le gestionnaire de réussite ajax pour faire quelque chose comme ceci:
success: function(json,status) {
window.location.href = json.url;
}
Mais cela signifie que je devrais faire plusieurs appels au serveur, et mon serveur devrait créer des fichiers téléchargeables, les stocker quelque part, puis nettoyer périodiquement cette zone de stockage.
Il doit y avoir un moyen plus simple d'accomplir cela. Des idées?
EDIT: Après avoir examiné les documents pour $ .ajax, je vois que la réponse dataType ne peut être que l'un xml, html, script, json, jsonp, text
, donc je suppose qu'il n'y a aucun moyen de télécharger directement un fichier à l'aide d'une demande ajax, à moins que j'incorpore le fichier binaire en utilisant Schéma d'URI de données comme suggéré dans la réponse @VinayC (ce qui n'est pas quelque chose que je veux faire).
Je suppose donc que mes options sont les suivantes:
N'utilisez pas ajax et soumettez plutôt un post de formulaire et intégrez mes données JSON dans les valeurs du formulaire. Aurait probablement besoin de jouer avec des iframes cachés et autres.
N'utilisez pas ajax et convertissez plutôt mes données JSON en une chaîne de requête pour créer une demande GET standard et définissez window.location.href sur cette URL. Peut-être besoin d'utiliser event.preventDefault () dans mon gestionnaire de clics pour empêcher le navigateur de changer à partir de l'URL de l'application.
Utilisez mon autre idée ci-dessus, mais améliorée avec des suggestions de la réponse @naikus. Soumettez la demande AJAX avec un paramètre qui permet au service Web de savoir que cela est appelé via un appel ajax. Si le service Web est appelé à partir d'un appel ajax, renvoyez simplement JSON avec une URL vers la ressource générée. Si la ressource est appelée directement, renvoyez le fichier binaire réel.
Plus j'y pense, plus j'aime la dernière option. De cette façon, je peux récupérer des informations sur la demande (temps de génération, taille du fichier, messages d'erreur, etc.) et je peux agir sur ces informations avant de démarrer le téléchargement. L'inconvénient est une gestion supplémentaire des fichiers sur le serveur.
D'autres moyens d'y parvenir? Y a-t-il des avantages / inconvénients à ces méthodes que je devrais connaître?
url = 'http://localhost/file.php?file='+ $('input').val(); window.open(url);
La manière simple d'obtenir les mêmes résultats. Mettez l'en-tête dans le fichier php. Pas besoin d'envoyer un ajax ou d'obtenir des demandes