Angular 2 скачать PDF из API и отобразить его в представлении

Я изучаю Angular 2 Beta. Интересно, как загрузить PDF-файл из API и отобразить его на мой взгляд? Я попытался сделать запрос, используя следующее:

var headers = new Headers(); headers.append('Accept', 'application/pdf'); var options = new ResponseOptions({ headers: headers }); var response = new Response(options); this.http.get(this.setUrl(endpoint), response).map(res => res.arrayBuffer()).subscribe(r=>{ console.log(r); }) 
  • Обратите внимание, что я использую только console.log чтобы увидеть значение r

Но я всегда получаю следующее сообщение об исключении:

Метод arrayBuffer () не реализован в суперclassе Response

Это потому, что этот метод еще не готов в Angular 2 Beta? Или есть какая-то ошибка, которую я сделал?

Любая помощь будет оценена по достоинству. Большое спасибо.

Фактически эта функция еще не реализована в поддержке HTTP.

В качестве обходного пути вам необходимо расширить class BrowserXhr Angular2, как описано ниже, чтобы установить responseType в blob на базовом объекте xhr:

 import {Injectable} from 'angular2/core'; import {BrowserXhr} from 'angular2/http'; @Injectable() export class CustomBrowserXhr extends BrowserXhr { constructor() {} build(): any { let xhr = super.build(); xhr.responseType = "blob"; return (xhr); } } 

Затем вам нужно обернуть полезную нагрузку ответа в объект Blob и использовать библиотеку FileSaver, чтобы открыть диалоговое окно загрузки:

 downloadFile() { this.http.get( 'https://mapapi.apispark.net/v1/images/Granizo.pdf').subscribe( (response) => { var mediaType = 'application/pdf'; var blob = new Blob([response._body], {type: mediaType}); var filename = 'test.pdf'; saveAs(blob, filename); }); } 

Библиотека FileSaver должна быть включена в ваш HTML-файл:

  

См. Этот plunkr: http://plnkr.co/edit/tfpS9k2YOO1bMgXBky5Y?p=preview

К сожалению, это установит responseType для всех запросов AJAX. Чтобы иметь возможность установить значение этого свойства, в XHRConnection и Http есть больше обновлений.

В качестве ссылок см. Следующие ссылки:

  • Загрузить pdf-файл с помощью jquery ajax
  • Получать zip-файл, angularJs

редактировать

Подумав немного больше, я думаю, что вы можете использовать иерархические инжекторы и настроить этого провайдера только на уровне компонента, который выполняет загрузку:

 @Component({ selector: 'download', template: '
Download
' , providers: [ provide(CustomBrowserXhr, { useClass: CustomBrowserXhr } ] }) export class DownloadComponent { @Input() filename:string; constructor(private http:Http) { } downloadFile() { this.http.get( 'https://mapapi.apispark.net/v1/images/'+this.filename).subscribe( (response) => { var mediaType = 'application/pdf'; var blob = new Blob([response._body], {type: mediaType}); var filename = 'test.pdf'; saveAs(blob, filename); }); } }

Это переопределение будет применяться только к этому компоненту (не забудьте удалить соответствующий код при загрузке приложения). Компонент загрузки можно использовать следующим образом:

 @Component({ selector: 'somecomponent', template: `  ` , directives: [ DownloadComponent ] }) 

Итак, вот как мне удалось заставить его работать. Моя ситуация: мне нужно было загрузить PDF-файл из конечной точки API и сохранить результат в формате PDF в браузере.

Для поддержки сохранения файлов во всех браузерах я использовал модуль FileSaver.js .

Я создал компонент, который принимает идентификатор файла для загрузки в качестве параметра. Компонент, , называется так:

  

Сам компонент использует XHR для извлечения / сохранения файла с номером, указанным в параметре no . Таким образом, мы можем обойти тот факт, что модуль Angular2 http еще не поддерживает двоичные типы результатов.

И теперь, без лишнего шума, код компонента:

  import {Component,Input } from 'angular2/core'; import {BrowserXhr} from 'angular2/http'; // Use Filesaver.js to save binary to file // https://github.com/eligrey/FileSaver.js/ let fileSaver = require('filesaver.js'); @Component({ selector: 'pdf-downloader', template: `  ` }) export class PdfDownloader { @Input() no: any; public pending:boolean = false; constructor() {} public download() { // Xhr creates new context so we need to create reference to this let self = this; // Status flag used in the template. this.pending = true; // Create the Xhr request object let xhr = new XMLHttpRequest(); let url = `/api/pdf/iticket/${this.no}?lang=en`; xhr.open('GET', url, true); xhr.responseType = 'blob'; // Xhr callback when we get a result back // We are not using arrow function because we need the 'this' context xhr.onreadystatechange = function() { // We use setTimeout to trigger change detection in Zones setTimeout( () => { self.pending = false; }, 0); // If we get an HTTP status OK (200), save the file using fileSaver if(xhr.readyState === 4 && xhr.status === 200) { var blob = new Blob([this.response], {type: 'application/pdf'}); fileSaver.saveAs(blob, 'Report.pdf'); } }; // Start the Ajax request xhr.send(); } } 

Я использовал Font Awesome для шрифтов, используемых в шаблоне. Я хотел, чтобы компонент отображал кнопку загрузки и счетчик, в то время как PDF-файл был извлечен.

Кроме того, обратите внимание, что я могу использовать запрос для извлечения модуля fileSaver.js. Это потому, что я использую WebPack, поэтому я могу потребовать / импортировать, как я хочу. Ваш синтаксис может отличаться в зависимости от вашего инструмента построения.

Я не думаю, что все эти хаки необходимы. Я просто сделал быстрый тест со стандартным сервисом http в угловом 2.0, и он работал, как ожидалось.

 /* generic download mechanism */ public download(url: string, data: Object = null): Observable { //if custom headers are required, add them here let headers = new Headers(); //add search parameters, if any let params = new URLSearchParams(); if (data) { for (let key in data) { params.set(key, data[key]); } } //create an instance of requestOptions let requestOptions = new RequestOptions({ headers: headers, search: params }); //any other requestOptions requestOptions.method = RequestMethod.Get; requestOptions.url = url; requestOptions.responseType = ResponseContentType.Blob; //create a generic request object with the above requestOptions let request = new Request(requestOptions); //get the file return this.http.request(request) .catch(err => { /* handle errors */ }); } /* downloads a csv report file generated on the server based on search criteria specified. Save using fileSaver.js. */ downloadSomethingSpecifc(searchCriteria: SearchCriteria): void { download(this.url, searchCriteria) .subscribe( response => { let file = response.blob(); console.log(file.size + " bytes file downloaded. File type: ", file.type); saveAs(file, 'myCSV_Report.csv'); }, error => { /* handle errors */ } ); } 

Вот простейший способ загрузить файл из API, который я смог придумать.

 import { Injectable } from '@angular/core'; import { Http, ResponseContentType } from "@angular/http"; import * as FileSaver from 'file-saver'; @Injectable() export class FileDownloadService { constructor(private http: Http) { } downloadFile(api: string, fileName: string) { this.http.get(api, { responseType: 'blob' }) .subscribe((file: Blob) => { FileSaver.saveAs(file, fileName); }); } } 

Вызовите метод downloadFile(api,fileName) из вашего classа компонента.

Чтобы заставить FileSaver запускать следующие команды в вашем терминале

 npm install file-saver --save npm install @types/file-saver --save 

Привет , вот рабочий пример. Он также подходит для PDF! application / octet-stream – общий тип. controller:

 public FileResult exportExcelTest() { var contentType = "application/octet-stream"; HttpContext.Response.ContentType = contentType; RealisationsReportExcell reportExcell = new RealisationsReportExcell(); byte[] filedata = reportExcell.RunSample1(); FileContentResult result = new FileContentResult(filedata, contentType) { FileDownloadName = "report.xlsx" }; return result; } 

Angular2:

Служба xhr:

 import { Injectable } from '@angular/core'; import { BrowserXhr } from '@angular/http'; @Injectable() export class CustomBrowserXhr extends BrowserXhr { constructor() { super(); } public build(): any { let xhr = super.build(); xhr.responseType = "blob"; return (xhr); } } 

Установите файл-хранитель npm-пакетов «файл-заставка»: «^ 1.3.3», «@ types / file-saver»: «0.0.0» и включите в файл vendor.ts «файл-заставка»;

Компонент btn скачать.

 import { Component, OnInit, Input } from "@angular/core"; import { Http, ResponseContentType } from '@angular/http'; import { CustomBrowserXhr } from '../services/customBrowserXhr.service'; import * as FileSaver from 'file-saver'; @Component({ selector: 'download-btn', template: '', providers: [ { provide: CustomBrowserXhr, useClass: CustomBrowserXhr } ] }) export class DownloadComponent { @Input() api: string; constructor(private http: Http) { } public downloadFile() { return this.http.get(this.api, { responseType: ResponseContentType.Blob }) .subscribe( (res: any) => { let blob = res.blob(); let filename = 'report.xlsx'; FileSaver.saveAs(blob, filename); } ); } } 

С помощью

  

Вот код, который работает для загрузки API в IE и chrome / safari. Здесь переменная ответа – ответ API.

  let blob = new Blob([response], {type: 'application/pdf'}); let fileUrl = window.URL.createObjectURL(blob); if (window.navigator.msSaveOrOpenBlob) { window.navigator.msSaveOrOpenBlob(blob, fileUrl.split(':')[1] + '.pdf'); } else { window.open(fileUrl); } 

Чтобы заставить Файловый менеджер работать в Угловом 5: Установить

 npm install file-saver --save npm install @types/file-saver --save 

В вашем компоненте используйте import * as FileSaver from "file-saver";

и используйте FileSaver. по умолчанию, а не FileSaver. Сохранить как

 .subscribe(data => { const blob = data.data; const filename = "filename.txt"; FileSaver.default(blob, filename); 
  • Angular2 http.post выполняется дважды
  • Динамически установить значение ui-sref Angularjs
  • Перезагрузка текущего состояния - обновление данных
  • Как отменить Angular 2 Cli ng-eject?
  • ExpressionChangedAfterItHasBeenCheckedError Explained
  • Угловой 2.0 и модальный диалог
  • Угловой 2 выход с выхода маршрутизатора
  • Нет провайдера для AngularFireDatabase, AngularFireAuth
  • ПРЕДУПРЕЖДЕНИЕ: очистка небезопасного значения значения стиля
  • ключ доступа и значение объекта с помощью * ngFor
  • точный фильтр в угловом
  • Interesting Posts

    В чем разница между Swing и AWT?

    Перемещает ли вектор аннулировать iteratorы?

    Как я могу постоянно указывать Windows7 по умолчанию мои пользовательские данные, такие как библиотеки, кроме загрузочного диска?

    Android. Сохраняйте элемент списка ListView один раз, когда вы нажали

    RegEx соответствует номерам, разделенным запятой, с необязательной десятичной частью

    Отформатируйте защищенную (поврежденную) SD-карту

    Сначала вызовите removeView () родителя ребенка

    Как изменить настройки сети другого компьютера с Powershell и / или .NET?

    Как повторять уведомление ежедневно в определенное время в android через фоновое обслуживание

    Как я могу получить данные из firebase на мой адаптер

    Разбор большого json-файла в .NET.

    Бутстрап 3 Размер желоба

    XPath для выбора нескольких тегов

    Как сделать объемный микшер Windows 7 снова сохранить отдельные тома?

    Как удалить старую ОС из меню загрузки

    Давайте будем гением компьютера.