Disons que j'ai des liens de téléchargement pour les fichiers sur mon site.
Lorsque vous cliquez sur ces liens, envoyez une demande AJAX au serveur qui renvoie l'URL avec l'emplacement du fichier.
Ce que je veux faire, c'est demander au navigateur de télécharger le fichier lorsque la réponse sera de retour. Existe-t-il un moyen portable de le faire?
Essayez cette lib https://github.com/PixelsCommander/Download-File-JS c'est plus moderne que toutes les solutions décrites précédemment car utilise l'attribut "download" et une combinaison de méthodes pour apporter la meilleure expérience possible .
Expliqué ici - http://pixelscommander.com/en/javascript/javascript-file-downliading-ignore-content-type/
Semble être un morceau de code idéal pour commencer le téléchargement en JavaScript.
Nous procédons de cette façon: ajoutez d'abord ce script.
<script type="text/javascript">
function populateIframe(id,path)
{
var ifrm = document.getElementById(id);
ifrm.src = "download.php?path="+path;
}
</script>
Placez-le où vous voulez le bouton de téléchargement (ici, nous utilisons juste un lien):
<iframe id="frame1" style="display:none"></iframe>
<a href="javascript:populateIframe('frame1','<?php echo $path; ?>')">download</a>
Le fichier 'download.php' (qui doit être placé sur votre serveur) contient simplement:
<?php
header("Content-Type: application/octet-stream");
header("Content-Disposition: attachment; filename=".$_GET['path']);
readfile($_GET['path']);
?>
Ainsi, lorsque vous cliquez sur le lien, l'iframe caché obtient/ouvre le fichier source 'download.php'. Avec le chemin d'accès comme paramètre get. Nous pensons que c'est la meilleure solution!
Il convient de noter que la partie PHP de cette solution est une démonstration simple et potentiellement très, très peu sûre. Elle permet à l'utilisateur de télécharger n'importe quel fichier, pas seulement un ensemble prédéfini. Cela signifie ils pourraient télécharger des parties du code source du site lui-même, contenant éventuellement des informations d'identification API, etc.
J'ai créé un open source plugin jQuery File Download ( Démo avec des exemples ) ( GitHub ) qui pourrait également vous aider dans votre situation. Il fonctionne de manière assez similaire avec un iframe mais a quelques fonctionnalités intéressantes que j'ai trouvées assez pratiques:
En lisant les réponses - y compris celle acceptée, je voudrais souligner les implications en matière de sécurité de la transmission directe d'un chemin au fichier de lecture via GET.
Cela peut sembler évident pour certains, mais certains peuvent simplement copier/coller ce code:
<?php
header("Content-Type: application/octet-stream");
header("Content-Disposition: attachment; filename=".$_GET['path']);
readfile($_GET['path']);
?>
Que se passe-t-il si je passe quelque chose comme '/ path/to/fileWithSecrets' à ce script? Le script donné enverra avec plaisir tout fichier auquel l'utilisateur du serveur Web a accès.
Veuillez vous référer à cette discussion pour savoir comment éviter cela: Comment puis-je m'assurer qu'un chemin de fichier se trouve dans un sous-répertoire donné?
Si c'est votre propre application serveur, je suggère d'utiliser l'en-tête suivant
Content-disposition: attachment; filename=fname.ext
Cela forcera tout navigateur à télécharger le fichier et non à le rendre dans la fenêtre du navigateur.
Il suffit d'appeler window.location.href = new_url
à partir de votre javascript et il redirigera le navigateur vers cette URL telle que l'utilisateur l'a tapée dans la barre d'adresse
Acceptez les méthodes mentionnées par maxnk, mais vous voudrez peut-être reconsidérer la tentative de forcer automatiquement le navigateur à télécharger l'URL. Cela peut fonctionner correctement pour les fichiers binaires mais pour d'autres types de fichiers (texte, PDF, images, vidéo), le navigateur peut vouloir le rendre dans la fenêtre (ou IFRAME) plutôt que de l'enregistrer sur le disque.
Si vous avez vraiment besoin d'appeler Ajax pour obtenir les liens de téléchargement finaux, qu'en est-il de l'utilisation de DHTML pour écrire dynamiquement le lien de téléchargement (à partir de la réponse ajax) dans la page? De cette façon, l'utilisateur pourrait soit cliquer dessus pour télécharger (si binaire) ou afficher dans son navigateur - ou sélectionner "Enregistrer sous" sur le lien pour enregistrer sur le disque. C'est un clic supplémentaire, mais l'utilisateur a plus de contrôle.
Pour contourner la faille de sécurité dans la réponse la plus votée, vous pouvez définir le iframe src directement sur le fichier que vous souhaitez (au lieu d'un fichier php intermédiaire) et définir les informations d'en-tête dans un fichier .htaccess:
<Files *.apk>
ForceType application/force-download
Header set Content-Disposition attachment
Header set Content-Type application/vnd.Android.package-archive
Header set Content-Transfer-Encoding binary
</Files>
En ce qui concerne la première réponse, j'ai une solution possible au risque de sécurité.
<?php
if(isset($_GET['path'])){
if(in_array($_GET['path'], glob("*/*.*"))){
header("Content-Type: application/octet-stream");
header("Content-Disposition: attachment; filename=".$_GET['path']);
readfile($_GET['path']);
}
}
?>
En utilisant la fonction glob () (j'ai testé le fichier de téléchargement dans un chemin d'accès d'un dossier à partir du fichier à télécharger), j'ai pu créer un tableau rapide de fichiers qui sont "autorisés" à être téléchargés et j'ai vérifié le chemin d'accès par rapport à celui-ci . Cela garantit non seulement que le fichier saisi n'est pas quelque chose de sensible, mais vérifie également l'existence des fichiers en même temps.
~ Remarque: Javascript/HTML ~
HTML:
<iframe id="download" style="display:none"></iframe>
et
<input type="submit" value="Download" onclick="ChangeSource('document_path');return false;">
JavaScript:
<script type="text/javascript">
<!--
function ChangeSource(path){
document.getElementByID('download').src = 'path_to_php?path=' + document_path;
}
-->
</script>
Je suggère de créer un iframe invisible sur la page et de définir son src sur l'URL que vous avez reçue du serveur - le téléchargement commencera sans rechargement de page.
Ou vous pouvez simplement définir le document.location.href actuel sur l'adresse URL reçue. Mais cela peut amener l'utilisateur à voir une erreur si le document demandé n'existe pas.
Pourquoi faites-vous des choses côté serveur alors que tout ce dont vous avez besoin est de rediriger le navigateur vers différents window.location.href?
Voici le code qui analyse? File = QueryString ( tiré de cette question ) et redirige l'utilisateur vers cette adresse en 1 seconde (fonctionne pour moi même sur Android):
<script type="text/javascript">
var urlParams;
(window.onpopstate = function () {
var match,
pl = /\+/g, // Regex for replacing addition symbol with a space
search = /([^&=]+)=?([^&]*)/g,
decode = function (s) { return decodeURIComponent(s.replace(pl, " ")); },
query = window.location.search.substring(1);
urlParams = {};
while (match = search.exec(query))
urlParams[decode(match[1])] = decode(match[2]);
})();
(window.onload = function() {
var path = urlParams["file"];
setTimeout(function() { document.location.href = path; }, 1000);
});
</script>
Si vous avez jQuery dans votre projet, supprimez définitivement ces gestionnaires window.onpopstate & window.onload et faites tout dans $ (document) .ready (function () {});
Je suggère window.open()
pour ouvrir une fenêtre contextuelle. S'il s'agit d'un téléchargement, il n'y aura pas de fenêtre et vous obtiendrez votre fichier. S'il y a un 404 ou quelque chose, l'utilisateur le verra dans une nouvelle fenêtre (par conséquent, son travail ne sera pas dérangé, mais il recevra toujours un message d'erreur).