2014-09-26 15 views
5

Scott's answer dayalı bir direktif yazdım. Öyle gibi kullanabilirsiniz istiyorum:AngularJs dinamik indir tepki

<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> 

Sayı: kod aşağıdaki ilk yöntemi (: saveBlob(blob, filename); çizgi) üzerinde IE11 bir hata TypeError: Invalid calling object atar. Diğer indirme yöntemlerine geri dönmesine rağmen, saveMethod1'in IE11'da çalışması gerektiği benim anlayışım. Herhangi bir yardım büyük takdir

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

       } 
      }; 
     } 
    ]); 

: Burada

kodudur!

+0

Dmitry, IE11 çalışmalarını deneme şansınız oldu mu? – Scott

+0

Üzgünüz, bu çalışmaları doğrulamak için bir şansım yoktu. Bu soruyu ayrı bir sekmede açtım çünkü biliyorum çok yakında geri döneceğim. Bunu bir kez verdiğimde size geri bildirim vereceğim. Sorunu incelediğin için teşekkür ederim! – Dmitry

+0

Endişelenmeyin :) Teşekkürler – Scott

cevap

5

Sorun:

Bu sorunu çözdüm.

// 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"); 

Yani esasen müsaade olmalıdır saveBlob işlevselliği, saklanması için oluşturulan jenerik takma beklendiği gibi çalışmasını msSaveBlob önler: Internet Explorer 11 basit örneklerle gösterdi msSaveBlob işlevine adlar sevmez anlaşılıyor :

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

Çözüm:

Yani etrafında çalışma ayrı ayrı msSaveBlob için test etmektir.

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; dr

Yani msSaveBlob yöntem sürece işlevini diğer ad yok gibi çalışır. Belki de bu bir güvenlik önlemi - ama belki de bir güvenlik istisnası daha uygun olurdu, büyük ihtimalle kaynak düşünüldüğünde bir kusur olduğunu düşünüyorum. :)

+1

bu harika çalıştı! Araştırmanız için teşekkürler – Dmitry

+0

@Dmitry Harika, işe yaradığı için memnun oldum. :) – Scott

+0

@Scott, buradan sadece I.E 11'de yakalanacak, var blob = new Blob ([data], {type: contentType}); – cracker