Cara Menampilkan blob (.pdf) di aplikasi AngularJS

106

Saya mencoba menampilkan file pdf yang saya dapatkan sebagai blob dari file $http.post respons. PDF harus ditampilkan dalam aplikasi menggunakan <embed src>misalnya.

Saya menemukan beberapa tumpukan posting tetapi entah bagaimana contoh saya sepertinya tidak berfungsi.

JS:

Menurut dokumen ini , saya melanjutkan dan mencoba ...

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

Nah dari apa yang saya pahami, fileURLbuatlah URL sementara yang bisa digunakan blog sebagai referensi.

HTML:

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

Saya tidak yakin bagaimana menangani ini di Angular, situasi yang ideal adalah (1) menetapkannya ke ruang lingkup, (2) 'mempersiapkan / membangun kembali' blob ke pdf (3) meneruskannya ke HTML menggunakan <embed>karena saya ingin menampilkannya di dalam aplikasi.

Saya telah meneliti selama lebih dari satu hari sekarang tetapi entah bagaimana saya sepertinya tidak dapat memahami cara kerjanya di Angular ... Dan anggap saja perpustakaan penampil pdf di luar sana tidak ada pilihan.

Simo D'lo Mafuxwana
sumber
Halo D'lo DeProjuicer, apakah Anda berhasil mendapatkan masalah dalam menghasilkan PDF melalui angular fixed?
Raymond Nakampe
@michael D'lo DeProjuicer Apa yang harus dilakukan untuk kasus yang sama di sudut 2?
monica

Jawaban:

214

Pertama-tama, Anda perlu menyetel responseTypeke arraybuffer. Ini diperlukan jika Anda ingin membuat blob dari data Anda. Lihat Sending_and_Receiving_Binary_Data . Jadi kode Anda akan terlihat seperti ini:

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

Bagian selanjutnya adalah, Anda perlu menggunakan layanan $ sce untuk mempercayai sudut url Anda. Ini dapat dilakukan dengan cara ini:

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

Jangan lupa untuk menginjeksi layanan $ sce .

Jika ini semua sudah selesai Anda sekarang dapat menyematkan pdf Anda:

<embed ng-src="{{content}}" style="width:200px;height:200px;"></embed>
michael
sumber
9
Bagi saya ini tidak berfungsi di Chrome (35.0.1916.114 m). Selesaikan ini dengan menggunakan <object> alih-alih <embed>: <object data = "{{content}}" type = "application / pdf"> </object>
HoffZ
2
Bagi saya (AngularJS 1.25) saya harus melakukan: Blob baru ([response.data]
Martin Connell
2
@HoffZ: Saya mengganti metode pintasan $http.getdengan yang lengkap, menentukan responseTypebidangnya: { 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' }Dan berhasil :)
Nikolay Melnikov
1
Bagi saya satu-satunya cara untuk membuat pekerjaan itu untuk membuat gumpalan dengan response.databukan response, seperti ini:var file = new Blob([response.data], {type: 'application/pdf'});
Alekos Filini
1
@ yosep-kim ini tidak berfungsi di IE karena objek URL tidak ada di IE: caniuse.com/#search=URL
Carlos
32

Saya menggunakan AngularJS v1.3.4

HTML:

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

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

Layanan JS:

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

Layanan Web REST Java - 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
sumber
versi safari yang mana? window.URL bagus di safari 9 dan setelahnya: caniuse.com/#search=createObjectURL
Stéphane GRILLON
Saya menguji dan menilai pada MacBook pro dan safari 9.0.2 saya.
Stéphane GRILLON
Sama, macBook el captain. window.URL.createObjectURL (file); saya tidak di mana masalahnya tetapi kode tidak berfungsi. Mungkin saya melakukan sesuatu yang salah. Terima kasih. Saya tidak punya waktu untuk memeriksa apa yang tidak berfungsi dan menggunakan FileSaver.js
fdrv
jika aplikasi Anda online, tolong posting URL Anda? apakah kamu punya Back-End yang sama?
Stéphane GRILLON
atribut unduhan tidak didukung di safari. caniuse.com/#search=download
Biswanath
21

saran michael bekerja seperti pesona bagi saya :) Jika Anda mengganti $ http.post dengan $ http.get, ingatlah bahwa metode .get menerima 2 parameter, bukan 3 ... di sinilah waktu saya terbuang ...;)

pengontrol:

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

melihat:

<object ng-show="content" data="{{content}}" type="application/pdf" style="width: 100%; height: 400px;"></object>
Jan Tchärmän
sumber
responseType:'arraybuffer', baru saja menghemat beberapa jam tidur! +1
svarog
bagaimana cara memicu penyimpanan alih-alih mencetaknya dalam html?
fdrv
terima kasih, ini menyelamatkan saya beberapa jam, Anda juga bisa mengganti $scope.content = $sce.trustAsResourceUrl(fileURL);dengan $window.open(fileURL, '_self', '');dan membuka file di fullscreen.
Tavitos
9

Saya menghadapi kesulitan dalam menggunakan "window.URL" dengan Opera Browser karena akan mengakibatkan "tidak terdefinisi". Juga, dengan window.URL, dokumen PDF tidak pernah dibuka di Internet Explorer dan Microsoft Edge (akan tetap menunggu selamanya). Saya datang dengan solusi berikut yang berfungsi di IE, Edge, Firefox, Chrome dan Opera (belum diuji dengan 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);
    }
}

Beri tahu saya jika itu membantu! :)

Manuel Hernandez
sumber
Pendekatan ini tidak membuka dokumen PDF di jendela browser di IE tetapi meminta pengguna untuk mendownloadnya. Apakah ada solusi untuk mengatasi ini?
sdd
1
Kode di atas adalah untuk mendownload file PDF dan biarkan aplikasi PDF Reader default Anda mengambil alih untuk membukanya. Bahkan berfungsi dengan baik di perangkat seluler. Alasannya adalah, meskipun saya dapat membuka PDF di beberapa browser, saya tidak dapat membukanya di browser lain. Jadi saya pikir yang terbaik adalah memiliki solusi yang akan berjalan di semua browser (termasuk browser seluler) untuk mengunduh file PDF.
Manuel Hernandez
Anda dapat menggunakan kode berikut untuk melihat PDF di tab baru: window.open (reader.result, '_blank');
samneric
6

Menambahkan responseType ke permintaan yang dibuat dari sudut memang solusinya, tetapi bagi saya itu tidak berhasil sampai saya menetapkan responseType ke blob , bukan ke arrayBuffer. Kode tersebut cukup jelas:

    $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
sumber
2
sebenarnya, dengan 'blob'jenis itu mungkin untuk menulis lebih pendek: FileSaver.saveAs(response.data, getFileNameFromHttpResponse(response));Tidak perlu membuatBlob
Alena Kastsiukavets
0

Saya telah berjuang selama beberapa hari terakhir mencoba mengunduh pdf dan gambar, yang bisa saya unduh hanyalah file teks sederhana.

Sebagian besar pertanyaan memiliki komponen yang sama, tetapi perlu waktu beberapa saat untuk menemukan urutan yang tepat agar dapat berfungsi.

Terima kasih @Nikolay Melnikov, komentar / balasan Anda atas pertanyaan ini yang membuatnya berhasil.

Singkatnya, inilah panggilan backend AngularJS Service saya:

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

Dari pengontrol saya:

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

Jawaban terbaru (untuk 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
sumber
-1

Saran kode yang baru saja saya gunakan dalam proyek saya menggunakan 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;" />
Fernando Magno
sumber
1
tolong tambahkan sedikit juga.
Farhana