Cách hiển thị blob (.pdf) trong ứng dụng AngularJS


106

Tôi đã cố gắng hiển thị tệp pdf mà tôi nhận được dưới dạng một đốm màu từ $http.postphản hồi. <embed src>Ví dụ: pdf phải được hiển thị trong ứng dụng .

Tôi đã xem qua một vài bài viết ngăn xếp nhưng bằng cách nào đó, ví dụ của tôi dường như không hoạt động.

JS:

Theo tài liệu này , tôi đã tiếp tục và thử ...

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

Bây giờ từ những gì tôi hiểu, hãy fileURLtạo một URL tạm thời mà blog có thể sử dụng làm tài liệu tham khảo.

HTML:

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

Tôi không chắc làm thế nào để xử lý điều này trong Angular, tình huống lý tưởng sẽ là (1) gán nó vào một phạm vi, (2) 'chuẩn bị / xây dựng lại' blob thành một pdf (3) chuyển nó sang HTML bằng cách sử dụng <embed>vì tôi muốn hiển thị nó trong ứng dụng.

Tôi đã nghiên cứu hơn một ngày nay nhưng bằng cách nào đó, tôi dường như không thể hiểu cách hoạt động của nó trong Angular ... Và hãy giả sử rằng các thư viện trình xem pdf ngoài kia không có tùy chọn.


Xin chào D'lo DeProjuicer, bạn có khắc phục được sự cố tạo PDF qua góc không?
Raymond Nakampe

@michael D'lo DeProjuicer Nên làm gì cho trường hợp tương tự trong góc 2?
monica

Câu trả lời:


214

Trước hết bạn cần phải thiết lập responseTypeđể arraybuffer. Điều này là bắt buộc nếu bạn muốn tạo một khối dữ liệu của mình. Xem Sending_and_Receiving_Binary_Data . Vì vậy, mã của bạn sẽ giống như sau:

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

Phần tiếp theo là bạn cần sử dụng dịch vụ $ trượng để tạo độ tin cậy cho url của bạn. Điều này có thể được thực hiện theo cách này:

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

Đừng quên sử dụng dịch vụ $ Quyền trượng .

Nếu tất cả điều này được thực hiện, bây giờ bạn có thể nhúng pdf của mình:

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

9
Đối với tôi, điều này không hoạt động trong Chrome (35.0.1916.114 m). Đã giải quyết vấn đề này bằng cách sử dụng <object> thay vì <embed>: <object data = "{{content}}" type = "application / pdf"> </object>
HoffZ

2
Đối với tôi (AngularJS 1.25) Tôi phải làm: Blob mới ([response.data]
Martin Connell

2
@HoffZ: Tôi thay thế các phương pháp tắt $http.getbằng một đầy đủ, xác định các responseTypelĩnh vực: { 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' }Và nó hoạt động :)
Nikolay Melnikov

1
Đối với tôi, cách duy nhất để làm cho nó làm việc là để tạo ra các blob với response.datathay vì response, như thế này:var file = new Blob([response.data], {type: 'application/pdf'});
Alekos Filini

1
@ yosep-kim này không làm việc trên IE vì đối tượng URL không tồn tại trong IE: caniuse.com/#search=URL
Carlos

32

Tôi sử dụng AngularJS v1.3.4

HTML:

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

Bộ điều khiển 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();
            });
        };
});

Dịch vụ JS:

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

Dịch vụ 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;
    }

phiên bản nào của safari? window.URL là tốt trong safari 9 và sau: caniuse.com/#search=createObjectURL
Stéphane Grillon

Tôi đã thử nghiệm và đánh giá trên MacBook pro và safari 9.0.2 của mình.
Stéphane GRILLON,

Tương tự, đội trưởng macBook el. window.URL.createObjectURL (tệp); tôi không có vấn đề ở đâu nhưng mã không hoạt động. Có thể tôi làm sai điều gì đó. Xin cảm ơn. Tôi không có thời gian để kiểm tra những gì nó không làm việc và sử dụng FileSaver.js
fdrv

nếu đơn đăng ký của bạn trực tuyến, vui lòng đăng URL của bạn? bạn có cùng Back-End không?
Stéphane GRILLON,

thuộc tính tải xuống không được hỗ trợ trong safari. caniuse.com/#search=download
Biswanath

21

Đề xuất của michael hoạt động như một sự quyến rũ đối với tôi :) Nếu bạn thay thế $ http.post bằng $ http.get, hãy nhớ rằng phương thức .get chấp nhận 2 tham số thay vì 3 ... đây là nơi lãng phí thời gian của tôi ...;)

bộ điều khiển:

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

lượt xem:

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

responseType:'arraybuffer', vừa tiết kiệm cho tôi một vài giờ ngủ! +1
svarog

Làm thế nào để kích hoạt lưu thay thế để in nó trong html?
fdrv

cảm ơn bạn, điều này đã tiết kiệm cho tôi một vài giờ, bạn cũng có thể thay thế $scope.content = $sce.trustAsResourceUrl(fileURL);bằng $window.open(fileURL, '_self', '');và mở tệp trên toàn màn hình.
Tavitos

9

Tôi đã gặp khó khăn khi sử dụng "window.URL" với Trình duyệt Opera vì nó sẽ dẫn đến "không xác định". Ngoài ra, với window.URL, tài liệu PDF không bao giờ được mở trong Internet Explorer và Microsoft Edge (nó sẽ vẫn chờ mãi mãi). Tôi đã đưa ra giải pháp sau hoạt động trên IE, Edge, Firefox, Chrome và Opera (chưa thử nghiệm với 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);
    }
}

Hãy cho tôi biết nếu nó có ích! :)


Cách tiếp cận này không mở tài liệu PDF trong cửa sổ trình duyệt của IE mà nhắc người dùng tải xuống. Có bất kỳ công việc xung quanh điều này?
sdd

1
Đoạn mã trên là để tải xuống tệp PDF và để ứng dụng Trình đọc PDF mặc định của bạn tiếp quản để mở tệp đó. Nó thậm chí còn hoạt động tốt trên các thiết bị di động. Lý do là, mặc dù tôi có thể mở PDF trên một số trình duyệt, nhưng tôi không thể mở nó trên các trình duyệt khác. Vì vậy, tôi nghĩ tốt nhất nên có một giải pháp chạy trên tất cả các trình duyệt (bao gồm cả trình duyệt dành cho thiết bị di động) để tải xuống tệp PDF.
Manuel Hernandez,

Bạn có thể sử dụng mã sau để xem PDF trong tab mới: window.open (reader.result, '_blank');
samneric

6

Thêm responseType vào yêu cầu được tạo từ angle thực sự là giải pháp, nhưng đối với tôi, nó không hoạt động cho đến khi tôi đặt responseType thành blob , không phải arrayBuffer. Mã tự giải thích:

    $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
trên thực tế, với 'blob'loại người ta có thể viết ngắn: FileSaver.saveAs(response.data, getFileNameFromHttpResponse(response));Không cần phải tạoBlob
Alena Kastsiukavets

0

Tôi đã vật lộn trong vài ngày qua khi cố gắng tải xuống các tệp pdf và hình ảnh, tất cả những gì tôi có thể tải xuống là các tệp văn bản đơn giản.

Hầu hết các câu hỏi đều có các thành phần giống nhau, nhưng phải mất một lúc để tìm ra thứ tự phù hợp để làm cho nó hoạt động.

Cảm ơn bạn @Nikolay Melnikov, nhận xét / trả lời của bạn cho câu hỏi này là điều khiến nó hoạt động.

Tóm lại, đây là cuộc gọi phụ trợ Dịch vụ AngularJS của tôi:

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

Từ bộ điều khiển của tôi:

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

Câu trả lời gần đây nhất (dành cho 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

Một gợi ý về mã mà tôi vừa sử dụng trong dự án của mình bằng 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
xin vui lòng thêm một số ngắn gọn quá.
Farhana
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.