web-dev-qa-db-fra.com

Afficher un blob (.pdf) dans une application angulaire

J'ai essayé d'afficher un fichier pdf que je reçois sous forme de blob à partir d'une réponse $http.post. Le pdf doit être affiché dans l'application à l'aide de <embed src> par exemple.

Je suis tombé sur quelques articles de pile mais mon exemple ne semble pas fonctionner.

JS:

Selon ce doc , je suis allé et essayé ...

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

D'après ce que j'ai compris, fileURL crée une URL temporaire que le blog peut utiliser comme référence.

HTML:

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

Je ne suis pas sûr de savoir comment gérer cela dans Angular, l'idéal serait de (1) l'attribuer à un scope, (2) 'préparer/reconstruire' le blob en pdf ( 3) transmettez-le au HTML à l'aide de <embed> car je souhaite l'afficher dans l'application.

Je fais des recherches depuis plus d'un jour, mais je n'arrive pas à comprendre comment cela fonctionne dans Angular ... Et supposons simplement que les bibliothèques de visionneuses de fichiers PDF n'étaient pas une option.

96
Simo D'lo Mafuxwana

Tout d’abord, vous devez définir responseType sur arraybuffer. Cela est nécessaire si vous souhaitez créer un blob de vos données. Voir Sending_and_Receiving_Binary_Data . Votre code ressemblera à ceci:

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

La partie suivante est, vous devez utiliser le service $ sce pour faire confiance à votre URL angulaire. Cela peut être fait de cette façon:

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

N'oubliez pas d'injecter le service $ sce .

Si tout cela est fait, vous pouvez maintenant intégrer votre pdf:

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

J'utilise AngularJS v1.3.4

HTML:

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

Contrôleur 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();
            });
        };
});

Services JS:

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

Services 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;
    }
30
sgrillon

les suggestions de michael fonctionnent comme un charme pour moi:) Si vous remplacez $ http.post par $ http.get, rappelez-vous que la méthode .get accepte 2 paramètres au lieu de 3 ... c'est ici que j'ai perdu mon temps .. .;)

manette:

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

vue:

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

J'ai eu des difficultés à utiliser "window.URL" avec le navigateur Opera car il en résulterait un "non défini". De plus, avec window.URL, le document PDF ne s'est jamais ouvert dans Internet Explorer et Microsoft Edge (il resterait en attente pour toujours). Je suis venu avec la solution suivante qui fonctionne dans IE, Edge, Firefox, Chrome et Opera (n'ont pas été testés avec 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);
    }
}

Faites-moi savoir si cela a aidé! :)

10
Manuel Hernandez

L'ajout de responseTypeà la requête créée par angular est la solution, mais pour moi cela n'a pas fonctionné tant que je n'ai pas défini responseType sur blob, et non pas arrayBuffer. Le code est explicite:

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

Ces derniers jours, j'ai eu du mal à télécharger des fichiers PDF et des images. Tout ce que j'ai pu télécharger, c'était de simples fichiers texte.

La plupart des questions ont les mêmes composantes, mais il a fallu un certain temps pour trouver le bon ordre pour que cela fonctionne.

Merci @Nikolay Melnikov, votre commentaire/réponse à cette question a été ce qui a fait en sorte que cela fonctionne.

En résumé, voici mon appel backend du service 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'
    });
  }

De mon contrôleur:

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