So zeigen Sie Blob (.pdf) in einer AngularJS-App an

106

Ich habe versucht, eine PDF-Datei anzuzeigen, die ich als Blob aus einer $http.postAntwort erhalte . Das PDF muss in der App mit angezeigt werden<embed src> .

Ich bin auf ein paar Stapelpfosten gestoßen, aber irgendwie scheint mein Beispiel nicht zu funktionieren.

JS:

Laut diesem Dokument habe ich weiter versucht ...

$http.post('/postUrlHere',{myParams}).success(function (response) {
 var file = new Blob([response], {type: 'application/pdf'});
 var fileURL = URL.createObjectURL(file);
 $scope.content = fileURL;
});

Soweit ich weiß, fileURL wird nun eine temporäre URL erstellt, die das Blog als Referenz verwenden kann.

HTML:

<embed src="{{content}}" width="200" height="200"></embed>

Ich bin mir nicht sicher, wie ich damit in Angular umgehen soll. Die ideale Situation wäre, (1) es einem Bereich zuzuweisen, (2) den Blob in ein PDF 'vorzubereiten / neu zu erstellen', (3) ihn an den HTML-Code zu übergeben, <embed>weil ich möchte es in der App anzeigen.

Ich habe seit mehr als einem Tag recherchiert, aber irgendwie kann ich nicht verstehen, wie das in Angular funktioniert ... Und nehmen wir einfach an, dass die PDF-Viewer-Bibliotheken da draußen keine Option waren.

Simo D'lo Mafuxwana
quelle
Hallo D'lo DeProjuicer, haben Sie es geschafft, Ihr Problem beim Generieren der PDF-Datei über einen Winkel zu beheben?
Raymond Nakampe
@michael D'lo DeProjuicer Was ist für den gleichen Fall in Winkel 2 zu tun?
Monica

Antworten:

214

Zunächst einmal müssen Sie die festlegen responseTypezu arraybuffer. Dies ist erforderlich, wenn Sie einen Blob Ihrer Daten erstellen möchten. Siehe Sending_and_Receiving_Binary_Data . Ihr Code sieht also folgendermaßen aus:

$http.post('/postUrlHere',{myParams}, {responseType:'arraybuffer'})
  .success(function (response) {
       var file = new Blob([response], {type: 'application/pdf'});
       var fileURL = URL.createObjectURL(file);
});

Der nächste Teil ist, dass Sie den $ sce- Dienst verwenden müssen, damit Angular Ihrer URL vertraut. Dies kann folgendermaßen geschehen:

$scope.content = $sce.trustAsResourceUrl(fileURL);

Vergessen Sie nicht, den $ sce- Service einzuschleusen .

Wenn dies alles erledigt ist, können Sie jetzt Ihr PDF einbetten:

<embed ng-src="{{content}}" style="width:200px;height:200px;"></embed>
Michael
quelle
9
Bei mir hat das in Chrome (35.0.1916.114 m) nicht funktioniert. Dies wurde behoben, indem <object> anstelle von <embed> verwendet wurde: <object data = "{{content}}" type = "application / pdf"> </ object>
HoffZ
2
Für mich (AngularJS 1.25) musste ich tun: neuer Blob ([response.data]
Martin Connell
2
@HoffZ: Ich habe die Verknüpfungsmethode $http.getdurch eine vollständige ersetzt und das responseTypeFeld angegeben: { url: "http://127.0.0.1:8080/resources/jobs/af471106-2e71-4fe6-946c-cd1809c659e5/result/?key="+$scope.key, method: "GET", headers: { 'Accept': 'application/pdf' }, responseType: 'arraybuffer' }Und es funktioniert :)
Nikolay Melnikov
1
Für mich war die einzige Möglichkeit, es zum response.dataresponsevar file = new Blob([response.data], {type: 'application/pdf'});
Laufen
1
@ yosep-kim dies funktioniert nicht im IE, da das URL-Objekt im IE nicht vorhanden ist: caniuse.com/#search=URL
Carlos
32

Ich benutze AngularJS v1.3.4

HTML:

<button ng-click="downloadPdf()" class="btn btn-primary">download PDF</button>

JS-Controller:

'use strict';
angular.module('xxxxxxxxApp')
    .controller('xxxxController', function ($scope, xxxxServicePDF) {
        $scope.downloadPdf = function () {
            var fileName = "test.pdf";
            var a = document.createElement("a");
            document.body.appendChild(a);
            a.style = "display: none";
            xxxxServicePDF.downloadPdf().then(function (result) {
                var file = new Blob([result.data], {type: 'application/pdf'});
                var fileURL = window.URL.createObjectURL(file);
                a.href = fileURL;
                a.download = fileName;
                a.click();
            });
        };
});

JS-Dienste:

angular.module('xxxxxxxxApp')
    .factory('xxxxServicePDF', function ($http) {
        return {
            downloadPdf: function () {
            return $http.get('api/downloadPDF', { responseType: 'arraybuffer' }).then(function (response) {
                return response;
            });
        }
    };
});

Java REST-Webdienste - Spring MVC:

@RequestMapping(value = "/downloadPDF", method = RequestMethod.GET, produces = "application/pdf")
    public ResponseEntity<byte[]> getPDF() {
        FileInputStream fileStream;
        try {
            fileStream = new FileInputStream(new File("C:\\xxxxx\\xxxxxx\\test.pdf"));
            byte[] contents = IOUtils.toByteArray(fileStream);
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.parseMediaType("application/pdf"));
            String filename = "test.pdf";
            headers.setContentDispositionFormData(filename, filename);
            ResponseEntity<byte[]> response = new ResponseEntity<byte[]>(contents, headers, HttpStatus.OK);
            return response;
        } catch (FileNotFoundException e) {
           System.err.println(e);
        } catch (IOException e) {
            System.err.println(e);
        }
        return null;
    }
Stéphane GRILLON
quelle
Welche Version der Safari? window.URL ist gut in Safari 9 und danach: caniuse.com/#search=createObjectURL
Stéphane GRILLON
Ich habe mein MacBook Pro und Safari 9.0.2 getestet und validiert.
Stéphane GRILLON
Gleich, MacBook El Captain. window.URL.createObjectURL (Datei); Ich weiß nicht, wo das Problem ist, aber Code funktioniert nicht. Vielleicht mache ich etwas falsch. Irgendwelche danke. Ich habe keine Zeit zu überprüfen, was es nicht funktioniert und FileSaver.js
fdrv
Wenn Ihre Bewerbung online ist, geben Sie bitte Ihre URL an. Hast du das gleiche Backend?
Stéphane GRILLON
Das Download-Attribut wird in Safari nicht unterstützt. caniuse.com/#search=download
Biswanath
21

Michaels Vorschläge wirken wie ein Zauber für mich :) Wenn Sie $ http.post durch $ http.get ersetzen, denken Sie daran, dass die .get-Methode 2 Parameter anstelle von 3 akzeptiert ... hier wird meine Zeit verschwendet ...;)

Regler:

$http.get('/getdoc/' + $stateParams.id,     
{responseType:'arraybuffer'})
  .success(function (response) {
     var file = new Blob([(response)], {type: 'application/pdf'});
     var fileURL = URL.createObjectURL(file);
     $scope.content = $sce.trustAsResourceUrl(fileURL);
});

Aussicht:

<object ng-show="content" data="{{content}}" type="application/pdf" style="width: 100%; height: 400px;"></object>
Jan Tchärmän
quelle
responseType:'arraybuffer', habe mir nur ein paar Schlafstunden erspart! +1
svarog
Wie kann man das Speichern auslösen, um es in HTML zu drucken?
Fdrv
danke, das mir ein paar Stunden gespeichert haben , können Sie auch ersetzen $scope.content = $sce.trustAsResourceUrl(fileURL);mit $window.open(fileURL, '_self', '');und die Datei auf Vollbild öffnen.
Tavitos
9

Ich hatte Probleme bei der Verwendung von "window.URL" mit Opera Browser, da dies zu "undefiniert" führen würde. Außerdem wurde mit window.URL das PDF-Dokument in Internet Explorer und Microsoft Edge nie geöffnet (es würde für immer warten). Ich habe die folgende Lösung gefunden, die in IE, Edge, Firefox, Chrome und Opera funktioniert (nicht mit Safari getestet):

$http.post(postUrl, data, {responseType: 'arraybuffer'})
.success(success).error(failed);

function success(data) {
   openPDF(data.data, "myPDFdoc.pdf");
};

function failed(error) {...};

function openPDF(resData, fileName) {
    var ieEDGE = navigator.userAgent.match(/Edge/g);
    var ie = navigator.userAgent.match(/.NET/g); // IE 11+
    var oldIE = navigator.userAgent.match(/MSIE/g); 

    var blob = new window.Blob([resData], { type: 'application/pdf' });

    if (ie || oldIE || ieEDGE) {
       window.navigator.msSaveBlob(blob, fileName);
    }
    else {
       var reader = new window.FileReader();
       reader.onloadend = function () {
          window.location.href = reader.result;
       };
       reader.readAsDataURL(blob);
    }
}

Lass es mich wissen, wenn es geholfen hat! :) :)

Manuel Hernandez
quelle
Dieser Ansatz öffnet das PDF-Dokument nicht im Browserfenster im IE, sondern fordert den Benutzer auf, es herunterzuladen. Gibt es eine Lösung dafür?
SDD
1
Mit dem obigen Code können Sie die PDF-Datei herunterladen und Ihre Standard-PDF-Reader-App zum Öffnen übernehmen. Es funktioniert sogar gut auf mobilen Geräten. Der Grund dafür ist, dass ich das PDF zwar in einigen Browsern öffnen konnte, in anderen jedoch nicht. Daher hielt ich es für das Beste, eine Lösung zu haben, die auf allen Browsern (einschließlich mobiler Browser) ausgeführt werden kann, um die PDF-Datei herunterzuladen.
Manuel Hernandez
Sie können den folgenden Code verwenden, um die PDF-Datei in einer neuen Registerkarte anzuzeigen: window.open (reader.result, '_blank');
Samneric
6

Hinzufügen response auf die Anforderung , die von Winkel hergestellt wird , ist in der Tat die Lösung, aber für mich ist es nicht funktioniert hat, bis ich festgelegt haben response zu Klecks , nicht zu Arraybuffer. Der Code ist selbsterklärend:

    $http({
            method : 'GET',
            url : 'api/paperAttachments/download/' + id,
            responseType: "blob"
        }).then(function successCallback(response) {
            console.log(response);
             var blob = new Blob([response.data]);
             FileSaver.saveAs(blob, getFileNameFromHttpResponse(response));
        }, function errorCallback(response) {   
        });
ancab
quelle
2
'blob'FileSaver.saveAs(response.data, getFileNameFromHttpResponse(response));Blob
Tatsächlich
0

Ich hatte in den letzten Tagen Probleme, PDFs und Bilder herunterzuladen. Alles, was ich herunterladen konnte, waren einfache Textdateien.

Die meisten Fragen haben die gleichen Komponenten, aber es hat eine Weile gedauert, bis die richtige Reihenfolge gefunden war, damit es funktioniert.

Vielen Dank an Nikolay Melnikov. Ihr Kommentar / Ihre Antwort auf diese Frage hat dazu beigetragen, dass es funktioniert hat.

Kurz gesagt, hier ist mein AngularJS Service-Backend-Aufruf:

  getDownloadUrl(fileID){
    //
    //Get the download url of the file
    let fullPath = this.paths.downloadServerURL + fileId;
    //
    // return the file as arraybuffer 
    return this.$http.get(fullPath, {
      headers: {
        'Authorization': 'Bearer ' + this.sessionService.getToken()
      },
      responseType: 'arraybuffer'
    });
  }

Von meinem Controller:

downloadFile(){
   myService.getDownloadUrl(idOfTheFile).then( (response) => {
      //Create a new blob object
      let myBlobObject=new Blob([response.data],{ type:'application/pdf'});

      //Ideally the mime type can change based on the file extension
      //let myBlobObject=new Blob([response.data],{ type: mimeType});

      var url = window.URL || window.webkitURL
      var fileURL = url.createObjectURL(myBlobObject);
      var downloadLink = angular.element('<a></a>');
      downloadLink.attr('href',fileURL);
      downloadLink.attr('download',this.myFilesObj[documentId].name);
      downloadLink.attr('target','_self');
      downloadLink[0].click();//call click function
      url.revokeObjectURL(fileURL);//revoke the object from URL
    });
}
Javier Carbajal
quelle
0

Letzte Antwort (für Angular 8+):

this.http.post("your-url",params,{responseType:'arraybuffer' as 'json'}).subscribe(
  (res) => {
    this.showpdf(res);
  }
)};

public Content:SafeResourceUrl;
showpdf(response:ArrayBuffer) {
  var file = new Blob([response], {type: 'application/pdf'});
  var fileURL = URL.createObjectURL(file);
  this.Content = this.sanitizer.bypassSecurityTrustResourceUrl(fileURL);
}

  HTML :

  <embed [src]="Content" style="width:200px;height:200px;" type="application/pdf" />
ashishpm
quelle
-1

Ein Vorschlag für Code, den ich gerade in meinem Projekt mit AngularJS v1.7.2 verwendet habe

$http.get('LabelsPDF?ids=' + ids, { responseType: 'arraybuffer' })
            .then(function (response) {
                var file = new Blob([response.data], { type: 'application/pdf' });
                var fileURL = URL.createObjectURL(file);
                $scope.ContentPDF = $sce.trustAsResourceUrl(fileURL);
            });

<embed ng-src="{{ContentPDF}}" type="application/pdf" class="col-xs-12" style="height:100px; text-align:center;" />
Fernando Magno
quelle
1
Bitte fügen Sie auch einige kurze hinzu.
Farhana