Как вы обслуживаете файл для загрузки с помощью AngularJS или Javascript?

У меня есть текст в скрытом текстовом поле. Когда нажимается кнопка, я хотел бы, чтобы текст был предложен для загрузки в виде файла .txt. Можно ли использовать AngularJS или Javascript?

Ответ 1

Вы можете сделать что-то подобное, используя Blob.

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

в вашем контроллере:

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

чтобы включить URL-адрес:

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

Обратите внимание, что

Каждый раз, когда вы вызываете createObjectURL(), создается новый URL-адрес объекта, даже если вы уже создали его для одного и того же объекта. Каждый из них должен быть освобожден, вызывая URL.revokeObjectURL(), когда они вам больше не нужны. Браузеры автоматически освободят их, когда документ будет выгружен; однако, для оптимальной производительности и использования памяти, если есть безопасные моменты, когда вы можете явно их выгружать, вы должны это сделать.

Источник: MDN

Ответ 2

Просто нажмите кнопку для загрузки, используя следующий код.

в html

<a class="btn" ng-click="saveJSON()" ng-href="{{ url }}">Export to JSON</a>

Ответ 3

Попробуйте это

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

и посетите этот сайт, это может быть полезно для вас.

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

Ответ 4

Это можно сделать в javascript без необходимости открывать другое окно браузера.

window.location.assign('url');

Замените 'url' ссылкой на ваш файл. Вы можете поместить это в функцию и вызвать ее с помощью ng-click, если вам нужно запустить загрузку с кнопки.

Ответ 5

В нашем текущем проекте на работе у нас был невидимый iFrame, и я должен был подать URL-адрес файла в iFrame, чтобы получить диалоговое окно загрузки. При нажатии кнопки контроллер генерирует динамический url и запускает событие $scope, где пользовательский directive, который я написал, является листингом. Директива добавит iFrame к телу, если он уже не существует и устанавливает на него атрибут url.

EDIT: добавление директивы

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;
});

Эта директива отвечает на событие контроллера с именем downloadFile

поэтому в своем контроллере вы делаете

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

Ответ 6

Вы можете установить location.href в URI данных, содержащий данные, которые вы хотите разрешить загрузке. Помимо этого, я не думаю, что есть способ сделать это только с помощью JavaScript.

Ответ 7

Хотелось бы добавить, что в случае, если он не загрузит файл из-за небезопасного: blob: null... когда вы наводите курсор на кнопку загрузки, вы должны его дезинфицировать. Например,

var app = angular.module('app', []);

app.config(функция ($ compileProvider) {

$compileProvider.aHrefSanitizationWhitelist(/^\s*(|blob|):/);

Ответ 8

У меня была одна и та же проблема, и я трачу много часов на поиск разных решений, и теперь я присоединяюсь ко всем комментариям в этом сообщении. Надеюсь, это будет полезно, мой ответ был правильно протестирован в Internet Explorer 11, Chrome и FireFox.

HTML:

<a href="#" class="btn btn-default" file-name="'fileName.extension'"  ng-click="getFile()" file-download="myBlobObject"><i class="fa fa-file-excel-o"></i></a>

ДИРЕКТИВ:

directive('fileDownload',function(){
    return{
        restrict:'A',
        scope:{
            fileDownload:'=',
            fileName:'=',
        },

        link:function(scope,elem,atrs){


            scope.$watch('fileDownload',function(newValue, oldValue){

                if(newValue!=undefined && newValue!=null){
                    console.debug('Downloading a new file'); 
                    var isFirefox = typeof InstallTrigger !== 'undefined';
                    var isSafari = Object.prototype.toString.call(window.HTMLElement).indexOf('Constructor') > 0;
                    var isIE = /*@[email protected]*/false || !!document.documentMode;
                    var isEdge = !isIE && !!window.StyleMedia;
                    var isChrome = !!window.chrome && !!window.chrome.webstore;
                    var isOpera = (!!window.opr && !!opr.addons) || !!window.opera || navigator.userAgent.indexOf(' OPR/') >= 0;
                    var isBlink = (isChrome || isOpera) && !!window.CSS;

                    if(isFirefox || isIE || isChrome){
                        if(isChrome){
                            console.log('Manage Google Chrome download');
                            var url = window.URL || window.webkitURL;
                            var fileURL = url.createObjectURL(scope.fileDownload);
                            var downloadLink = angular.element('<a></a>');//create a new  <a> tag element
                            downloadLink.attr('href',fileURL);
                            downloadLink.attr('download',scope.fileName);
                            downloadLink.attr('target','_self');
                            downloadLink[0].click();//call click function
                            url.revokeObjectURL(fileURL);//revoke the object from URL
                        }
                        if(isIE){
                            console.log('Manage IE download>10');
                            window.navigator.msSaveOrOpenBlob(scope.fileDownload,scope.fileName); 
                        }
                        if(isFirefox){
                            console.log('Manage Mozilla Firefox download');
                            var url = window.URL || window.webkitURL;
                            var fileURL = url.createObjectURL(scope.fileDownload);
                            var a=elem[0];//recover the <a> tag from directive
                            a.href=fileURL;
                            a.download=scope.fileName;
                            a.target='_self';
                            a.click();//we call click function
                        }


                    }else{
                        alert('SORRY YOUR BROWSER IS NOT COMPATIBLE');
                    }
                }
            });

        }
    }
})

В КОНТРОЛЛЕРЕ:

$scope.myBlobObject=undefined;
$scope.getFile=function(){
        console.log('download started, you can show a wating animation');
        serviceAsPromise.getStream({param1:'data1',param1:'data2', ...})
        .then(function(data){//is important that the data was returned as Aray Buffer
                console.log('Stream download complete, stop animation!');
                $scope.myBlobObject=new Blob([data],{ type:'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'});
        },function(fail){
                console.log('Download Error, stop animation and show error message');
                                    $scope.myBlobObject=[];
                                });
                            }; 

В СЕРВИСЕ:

function getStream(params){
                 console.log("RUNNING");
                 var deferred = $q.defer();

                 $http({
                     url:'../downloadURL/',
                     method:"PUT",//you can use also GET or POST
                     data:params,
                     headers:{'Content-type': 'application/json'},
                     responseType : 'arraybuffer',//THIS IS IMPORTANT
                    })
                    .success(function (data) {
                        console.debug("SUCCESS");
                        deferred.resolve(data);
                    }).error(function (data) {
                         console.error("ERROR");
                         deferred.reject(data);
                    });

                 return deferred.promise;
                };

BACKEND (на SPRING):

@RequestMapping(value = "/downloadURL/", method = RequestMethod.PUT)
public void downloadExcel(HttpServletResponse response,
        @RequestBody Map<String,String> spParams
        ) throws IOException {
        OutputStream outStream=null;
outStream = response.getOutputStream();//is important manage the exceptions here
ObjectThatWritesOnOutputStream myWriter= new ObjectThatWritesOnOutputStream();// note that this object doesn exist on JAVA,
ObjectThatWritesOnOutputStream.write(outStream);//you can configure more things here
outStream.flush();
return;
}

Ответ 9

Мне не нужен Static Url. У меня есть AjaxFactory для выполнения всех операций ajax. Я получаю url из factory и привязываю его следующим образом.

<a target="_self" href="{{ file.downloadUrl + '/' + order.OrderId + '/' + fileName }}" download="{{fileName}}">{{fileName}}</a>

Спасибо @AhlemMustapha

Ответ 10

Если у вас есть доступ к серверу, рассмотрите настройку заголовков как в этом более общем вопросе.

Content-Type: application/octet-stream
Content-Disposition: attachment;filename=\"filename.xxx\"

Считая комментарии к этому ответу, рекомендуется использовать более конкретный Content-Type, чем октетный поток.