98 votes

Comment servir un fichier à télécharger avec AngularJS ou Javascript ?

J'ai du texte dans une zone de texte cachée. Lorsqu'on clique sur un bouton, j'aimerais que le texte puisse être téléchargé sous la forme d'un fichier PDF. .txt fichier. Est-ce possible en utilisant AngularJS ou Javascript ?

1 votes

Quels sont les navigateurs que vous prenez en charge ? Cela peut être résolu de manière créative (comme les data-uris, les blobs, l'API de l'historique du navigateur, etc) mais cela dépend vraiment.

0 votes

Économiseur de fichiers angulaire est un bon polyfill pour les navigateurs moins modernes.

112voto

Tosh Points 13477

Vous pouvez faire quelque chose comme ça en utilisant Blob .

<a download="content.txt" ng-href="{{ url }}">download</a>

dans votre contrôleur :

var content = 'file content for example';
var blob = new Blob([ content ], { type : 'text/plain' });
$scope.url = (window.URL || window.webkitURL).createObjectURL( blob );

afin d'activer l'URL :

app = angular.module(...);
app.config(['$compileProvider',
    function ($compileProvider) {
        $compileProvider.aHrefSanitizationWhitelist(/^\s*(https?|ftp|mailto|tel|file|blob):/);
}]);

Veuillez noter que

Chaque fois que vous appelez createObjectURL(), une nouvelle URL d'objet est créée, même si vous en avez déjà créé une pour le même objet. Chacune de ces URL doit être libérée en appelant URL.revokeObjectURL() lorsque vous n'en avez plus besoin. Les navigateurs les libèrent automatiquement lorsque le document est déchargé. Toutefois, pour des performances et une utilisation de la mémoire optimales, si vous pouvez les décharger explicitement à des moments sûrs, vous devriez le faire.

Source : MDN

3 votes

Navigateurs modernes et IE10+

0 votes

@thriqon wow firefox + chrome montre vraiment les autres là-haut !

0 votes

Excellente solution, mais $scope.url n'a pas fonctionné pour moi. J'ai dû utiliser window.location à la place.

26voto

AhlemMustapha Points 79

Essayez ceci

<a target="_self" href="mysite.com/uploads/ahlem.pdf" download="foo.pdf">

et visitez ce site, il pourrait vous être utile :)

http://docs.angularjs.org/guide/

7 votes

Méfiez-vous de la download qui n'est toujours pas pris en charge par aucune version d'IE ou de Safari. Vérifiez ici : caniuse.com/#feat=download

0 votes

Quand je l'utilise avec angular, il prend l'url dans $urlRouterProvider et redirige vers ma page par défaut, y a-t-il une solution pour télécharger un fichier au lieu de la navigation ?

0 votes

Je trouve toujours condescendant quand quelqu'un poste un lien comme ça.

23voto

mm8154 Points 21

Cela peut être fait en javascript sans avoir besoin d'ouvrir une autre fenêtre du navigateur.

window.location.assign('url');

Remplacez "url" par le lien vers votre fichier. Vous pouvez mettre cela dans une fonction et l'appeler avec ng-click si vous devez déclencher le téléchargement à partir d'un bouton.

2 votes

Il remplace le site par un document Pdf pour afficher la fenêtre de dialogue de téléchargement.

0 votes

Merci ! Ça marche comme sur des roulettes.

14voto

Ketan Points 2871

Dans notre projet actuel au travail, nous avions un iFrame invisible et je devais fournir l'url du fichier à l'iFrame pour obtenir une boîte de dialogue de téléchargement. Lors du clic sur le bouton, le contrôleur génère l'url dynamique et déclenche un événement $scope dans lequel un objet personnalisé de type directive J'ai écrit, c'est la liste. La directive ajoutera une iFrame au corps s'il n'existe pas déjà et lui attribuera l'attribut url.

EDIT : Ajout d'une directive

appModule.directive('fileDownload', function ($compile) {
    var fd = {
        restrict: 'A',
        link: function (scope, iElement, iAttrs) {

            scope.$on("downloadFile", function (e, url) {
                var iFrame = iElement.find("iframe");
                if (!(iFrame && iFrame.length > 0)) {
                    iFrame = $("<iframe style='position:fixed;display:none;top:-1px;left:-1px;'/>");
                    iElement.append(iFrame);
                }

                iFrame.attr("src", url);

            });
        }
    };

    return fd;
});

Cette directive répond à un événement du contrôleur appelé downloadFile

donc dans votre contrôleur vous faites

$scope.$broadcast("downloadFile", url);

1 votes

Un extrait de code serait d'une grande aide.

0 votes

La directive ci-dessus ne fonctionne pas pour moi, lorsque je place la création de l'iframe en dehors du scope.$on, elle crée l'iframe mais l'événement $on n'est pas appelé lorsque j'utilise la diffusion.

0 votes

Oui $scope.$broadcast ne fonctionne que sur les enfants. Vous pouvez placer la directive sur le scope de premier niveau si possible.

12voto

Jani Hartikainen Points 23183

Vous pouvez définir location.href à un données URI contenant les données que vous voulez laisser l'utilisateur télécharger. En dehors de cela, je ne pense pas qu'il y ait un moyen de le faire avec juste JavaScript.

0 votes

Cela fonctionne très bien pour moi, et c'était beaucoup plus propre que toutes les autres choses que nous avons essayées, ou IMHO, les approches compliquées recommandées ci-dessus. Angular l'ignore complètement. Vous pouvez aussi utiliser window.open()/$window.open() si vous voulez essayer d'ouvrir dans une autre fenêtre. Mais vous vous heurterez à des bloqueurs de popup dans les navigateurs modernes...

1 votes

Dans Angular 1.3, $location.href changé en $window.location.href

0 votes

C'est une excellente réponse. Le lien suivant sur SO fournit un exemple fonctionnel complet : stackoverflow.com/a/30889331/1625820

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X