AngularJs从响应动态下载 [英] AngularJs dynamic download from response

查看:257
本文介绍了AngularJs从响应动态下载的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经写了基于斯科特的答案指令。你会使用它像这样:

I have written a directive based on Scott's answer. You'd use it like so:

<button class="btn btn-success"
        download-response="getData()"
        download-success="getDataSuccess()"
        download-error="getDataError()"
        download-name="{{name}}.pdf"
        download-backup-url="/Backup/File.pdf">
    Save
</button>

发行:的code以下抛出一个错误类型错误:无效的调用对象 IE11 上的第一个方法(行: saveBlob(BLOB,文件名); )。即使它回落到下载的其他方法,这是我的理解是,saveMethod1应 IE11 工作

Issue: the code below throws an error TypeError: Invalid calling object in IE11 on the first method (line: saveBlob(blob, filename);). Even though it falls back to other methods of downloading, it is my understanding that the saveMethod1 should work in IE11.

下面是code:

'use strict';

// directive allows to provide a function to be executed to get data to be downloaded
// attributes:
// download-response - Required. Function to get data. It must return a promise. It must be declared on the $scope.
// download-success - Optional. Function to be executed if download-response function was successfully resolved. It must be declared on the $scope.
// download-error - Optional. Function to be executed if download-response function return a promise rejection. It must be declared on the $scope.
// download-mime - Optional. provide a mime type of data being downloaded. Defaulted to "application/octet-stream"
// download-name - Optional. name of the file to download. Defaulted to "download.bin"
// download-backup-url - in case browser does not support dynamic download, this url will be called to get the file
angular.module('app.directives')
    .directive('downloadResponse', [ '$parse', '$timeout',
        function ($parse, $timeout) {

            function saveMethod1(data, filename, contentType) {
                // Support for saveBlob method (Currently only implemented in Internet Explorer as msSaveBlob, other extension in case of future adoption)
                var saveBlob = navigator.msSaveBlob || navigator.webkitSaveBlob || navigator.mozSaveBlob || navigator.saveBlob;

                if (saveBlob) {
                    // Save blob is supported, so get the blob as it's contentType and call save.
                    var blob = new Blob([data], { type: contentType });
                    saveBlob(blob, filename);
                    //console.log("SaveBlob Success");
                } else {
                    throw 'saveBlob is not supported. Falling back to the next method';
                }
            }

            function saveMethod2(data, filename, contentType, octetStreamMime) {
                // Get the blob url creator
                var urlCreator = window.URL || window.webkitURL || window.mozURL || window.msURL;
                if (urlCreator) {
                    // Try to use a download link
                    var link = document.createElement("a");
                    var url;
                    if ("download" in link) {
                        // Prepare a blob URL
                        var blob = new Blob([data], { type: contentType });
                        url = urlCreator.createObjectURL(blob);
                        link.setAttribute("href", url);

                        // Set the download attribute (Supported in Chrome 14+ / Firefox 20+)
                        link.setAttribute("download", filename);

                        // Simulate clicking the download link
                        var event = document.createEvent('MouseEvents');
                        event.initMouseEvent('click', true, true, window, 1, 0, 0, 0, 0, false, false, false, false, 0, null);
                        link.dispatchEvent(event);

                        //console.log("Download link Success");
                    } else {
                        // Prepare a blob URL
                        // Use application/octet-stream when using window.location to force download
                        var blob = new Blob([data], { type: octetStreamMime });
                        url = urlCreator.createObjectURL(blob);
                        window.location = url;

                        //console.log("window.location Success");
                    }
                } else {
                    throw 'UrlCreator not supported. Falling back to the next method';
                }
            }

            function saveMethod3(attrs) {
                if (attrs.downloadBackupUrl && attrs.downloadBackupUrl != '') {
                    console.log('opening ' + attrs.downloadBackupUrl);
                    window.open('http://' + document.domain + attrs.downloadBackupUrl, '_blank');
                } else {
                    throw 'Could not download a file using any of the available methods. Also you did not provide a backup download link. No more bullets left...';
                }
            }

            return {
                restrict: 'A',
                scope: false,
                link:function (scope, elm, attrs) {
                    var getDataHandler = $parse(attrs.downloadResponse);

                    elm.on('click', function() {
                        var promise = getDataHandler(scope);
                        promise.then(
                            function (data) {
                                if (attrs.downloadSuccess && attrs.downloadSuccess != '') {
                                    var successHandler = $parse(attrs.downloadSuccess);
                                    successHandler(scope);
                                }

                                var octetStreamMime = "application/octet-stream";

                                var filename = attrs.downloadName || "download.bin";
                                var contentType = attrs.downloadMime || octetStreamMime;


                                try {
                                    saveMethod1(data, filename, contentType);
                                    return;
                                } catch (e) {
                                    console.log(e);
                                    try {
                                        saveMethod2(data, filename, contentType, octetStreamMime);
                                        return;
                                    } catch (e) {
                                        console.log(e);
                                        try {
                                            saveMethod3(attrs);
                                            return;
                                        } catch (e) {
                                            throw e;
                                        } 
                                        throw e;
                                    } 
                                    throw e;
                                }
                            },
                            function(data) {
                                if (attrs.downloadError && attrs.downloadError != '') {
                                    var errorHandler = $parse(attrs.downloadError);
                                    errorHandler(scope);
                                }
                            }
                        );
                    });

                }
            };
        }
    ]);

任何帮助是极大AP preciated!

Any help is greatly appreciated!

推荐答案

我已经解决了这个问题。看来的Internet Explorer 11不喜欢的别名到 msSaveBlob 功能,通过最简单的例子证明:

Problem:

I have resolved this issue. It appears that Internet Explorer 11 does not like aliases to the msSaveBlob function, demonstrated by the simplest examples:

// Succeeds
navigator.msSaveBlob(new Blob(["Hello World"]), "test.txt");

// Fails with "Invalid calling object"
var saveBlob = navigator.msSaveBlob;
saveBlob(new Blob(["Hello World"]), "test.txt");

所以基本上创建封装 saveBlob 功能通用的别名,这应该是允许的,prevents msSaveBlob 按预期工作:

So essentially the generic alias created to encapsulate saveBlob functionality, which should be permissible, prevents msSaveBlob from working as expected:

var saveBlob = navigator.msSaveBlob || navigator.webkitSaveBlob || navigator.mozSaveBlob || navigator.saveBlob;

解决方案:

所以,解决办法是,以测试 msSaveBlob 分开。

if(navigator.msSaveBlob)
    navigator.msSaveBlob(blob, filename);
else {
    // Try using other saveBlob implementations, if available
    var saveBlob = navigator.webkitSaveBlob || navigator.mozSaveBlob || navigator.saveBlob;
    if(saveBlob === undefined) throw "Not supported";
    saveBlob(blob, filename);
}

TL;博士

所以 msSaveBlob 方法的工作,只要你不别名功能。也许这是一个安全precaution - 的但随后也许安全异常将是更合适的,但我认为这是最有可能的一个缺陷,考虑到源。 :)

tl;dr

So the msSaveBlob method works, as long as you don't alias the function. Perhaps it's a security precaution - but then perhaps a security exception would have been more appropriate, though I think it is most likely a flaw, considering the source. :)

这篇关于AngularJs从响应动态下载的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆