Come visualizzare il blob (.pdf) in un'app AngularJS


106

Ho provato a visualizzare il file pdf che sto ottenendo come un BLOB da un file $http.post risposta. Il pdf deve essere visualizzato all'interno dell'app utilizzando <embed src>ad esempio.

Mi sono imbattuto in un paio di post dello stack ma in qualche modo il mio esempio non sembra funzionare.

JS:

Secondo questo documento , sono andato avanti e ho provato ...

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

Ora da quello che ho capito fileURL crea un URL temporaneo che il blog può utilizzare come riferimento.

HTML:

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

Non sono sicuro di come gestirlo in Angular, la situazione ideale sarebbe (1) assegnarlo a uno scope, (2) 'preparare / ricostruire' il blob in un pdf (3) passarlo all'HTML usando <embed>perché io desidera visualizzarlo all'interno dell'app.

Ho fatto ricerche per più di un giorno, ma in qualche modo non riesco a capire come funziona in Angular ... E supponiamo solo che le librerie del visualizzatore di PDF là fuori non fossero un'opzione.


Ciao D'lo DeProjuicer, sei riuscito a risolvere il tuo problema di generare il PDF tramite angolare fisso?
Raymond Nakampe

@michael D'lo DeProjuicer Cosa si dovrebbe fare per lo stesso caso in angolare 2?
monica

Risposte:


214

Prima di tutto devi impostare il responseTypea arraybuffer. Ciò è necessario se si desidera creare un BLOB dei dati. Vedere Sending_and_Receiving_Binary_Data . Quindi il tuo codice sarà simile a questo:

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

La parte successiva è che devi usare il servizio $ sce per rendere angolare il tuo URL. Questo può essere fatto in questo modo:

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

Non dimenticare di iniettare il servizio $ sce .

Se è tutto fatto, ora puoi incorporare il tuo pdf:

<embed ng-src="{{content}}" style="width:200px;height:200px;"></embed>

9
Per me questo non ha funzionato in Chrome (35.0.1916.114 m). Risolto il problema utilizzando <object> invece di <embed>: <object data = "{{content}}" type = "application / pdf"> </object>
HoffZ

2
Per me (AngularJS 1.25) dovevo fare: nuovo Blob ([response.data]
Martin Connell

2
@HoffZ: ho sostituito il metodo di scelta rapida $http.getcon uno completo, specificando il responseTypecampo: { 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' }E funziona :)
Nikolay Melnikov

1
Per me l'unico modo per farlo funzionare era creare il blob con response.datainvece di response, in questo modo:var file = new Blob([response.data], {type: 'application/pdf'});
Alekos Filini

1
@ yosep-kim questo non funziona su IE perché l'oggetto URL non esiste in IE: caniuse.com/#search=URL
Carlos

32

Uso AngularJS v1.3.4

HTML:

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

Controller JS:

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

Servizi JS:

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

Servizi Web Java REST - 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;
    }

quale versione di safari? window.URL è valido in Safari 9 e dopo: caniuse.com/#search=createObjectURL
Stéphane GRILLON

Ho provato e valutato sul mio MacBook pro e Safari 9.0.2.
Stéphane GRILLON

Lo stesso, MacBook El Captain. window.URL.createObjectURL (file); non dov'è il problema ma il codice non funziona. Forse ho fatto qualcosa di sbagliato. Qualsiasi grazie. Non ho tempo per controllare cosa non funziona e utilizzare FileSaver.js
fdrv

se la tua applicazione è online, inserisci il tuo URL per favore? hai lo stesso back-end?
Stéphane GRILLON

l'attributo di download non è supportato in Safari. caniuse.com/#search=download
Biswanath,

21

i suggerimenti di michael per me funzionano a meraviglia :) Se sostituisci $ http.post con $ http.get, ricorda che il metodo .get accetta 2 parametri invece di 3 ... è qui che si spreca il mio tempo ...;)

Controller:

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

Visualizza:

<object ng-show="content" data="{{content}}" type="application/pdf" style="width: 100%; height: 400px;"></object>

responseType:'arraybuffer', mi ha appena risparmiato un paio di ore di sonno! +1
svarog

come attivare il salvataggio invece di stamparlo in html?
fdrv

grazie, questo mi ha salvato un paio d'ore, si può anche sostituire $scope.content = $sce.trustAsResourceUrl(fileURL);con $window.open(fileURL, '_self', '');e aprire il file su schermo intero.
Tavitos

9

Ho incontrato difficoltà nell'usare "window.URL" con Opera Browser poiché risulterebbe "indefinito". Inoltre, con window.URL, il documento PDF non è mai stato aperto in Internet Explorer e Microsoft Edge (sarebbe rimasto in attesa per sempre). Ho trovato la seguente soluzione che funziona in IE, Edge, Firefox, Chrome e Opera (non l'ho testata con Safari):

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

Fammi sapere se ha aiutato! :)


Questo approccio non apre il documento PDF nella finestra del browser in IE, ma richiede all'utente di scaricarlo. C'è qualche lavoro intorno a questo?
sdd

1
Il codice sopra è quello di scaricare il file PDF e lasciare che la tua app PDF Reader predefinita prenda il sopravvento per aprirlo. Funziona bene anche sui dispositivi mobili. Il motivo è che, sebbene fossi in grado di aprire il PDF su alcuni browser, non potevo aprirlo su altri. Quindi ho pensato che fosse meglio avere una soluzione che potesse funzionare su tutti i browser (inclusi i browser mobili) per scaricare il file PDF.
Manuel Hernandez

È possibile utilizzare il codice seguente per visualizzare il PDF in una nuova scheda: window.open (reader.result, '_blank');
samnerico

6

L'aggiunta di responseType alla richiesta effettuata da angular è davvero la soluzione, ma per me non ha funzionato finché non ho impostato responseType su blob , non su arrayBuffer. Il codice è autoesplicativo:

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

2
in realtà, con il 'blob'tipo è possibile scrivere più breve: FileSaver.saveAs(response.data, getFileNameFromHttpResponse(response));Non è necessario creareBlob
Alena Kastsiukavets

0

Ho lottato negli ultimi due giorni cercando di scaricare PDF e immagini, tutto ciò che sono riuscito a scaricare erano semplici file di testo.

La maggior parte delle domande ha gli stessi componenti, ma ci è voluto un po 'per capire l'ordine giusto per farlo funzionare.

Grazie @Nikolay Melnikov, il tuo commento / risposta a questa domanda è stato ciò che l'ha fatto funzionare.

In poche parole, ecco la mia chiamata al backend del servizio AngularJS:

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

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

0

Risposta più recente (per 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" />

-1

Un suggerimento di codice che ho appena usato nel mio progetto utilizzando AngularJS v1.7.2

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

1
per favore aggiungi anche qualche breve.
Farhana
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.