23

I have an angular2 project with an ASP.Net Web API. I have code to retrieve a file path from my database which goes to a document on my server. I then want to display this document in the browser in a new tab. Does anybody have any suggestions how to do this?

I am happy to retrieve the file in either Angular2 (Typescript) or in my API and stream it down.

This is my attempt of retrieving it in my API but i cannot work out how to receive it in Angular2 and display it properly:

public HttpResponseMessage GetSOP(string partnum, string description)
    {
        var sopPath = _uow.EpicorService.GetSOP(partnum, description).Path;
        HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK);
        var stream = new FileStream(sopPath, FileMode.Open);
        result.Content = new StreamContent(stream);
        result.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/octet-stream");
        return result;
    }

Any help would be greatly appreciated.

Many Thanks!!!

DaRoGa
  • 1,848
  • 7
  • 29
  • 47
  • If you want to see it in another tab, why not just open a new tab to the API's URL and let the browser interpret the content? You'd probably need to use a mime type of "application/pdf" instead of "application/octet-stream". – LinuxDisciple Oct 28 '16 at 07:40
  • I wrote about getting and displaying pdf files in new tab in Angular 2 here, check out my answer: http://stackoverflow.com/questions/37046133/pdf-blob-is-not-showing-content-angular-2/39657478#39657478 – Stefan Svrkota Oct 28 '16 at 07:45
  • @StefanSvrkota would this work with my API as it is? Or would i need to make changes to return it in the right format? – DaRoGa Oct 28 '16 at 07:46
  • I'm not sure, try it. I can let you know later how my API looks. – Stefan Svrkota Oct 28 '16 at 07:51
  • OK im just implementing it and ill let you know :) – DaRoGa Oct 28 '16 at 07:52
  • any update on this? i see a anwer got accepted? – Jesse de gans Jun 08 '17 at 14:12

4 Answers4

44

First of all, you need to set options for your http request - set responseType to ResponseContentType.Blob, use blob() to read response as blob and set its type to application/pdf:

downloadPDF(): any {
    return this._http.get(url, { responseType: ResponseContentType.Blob }).map(
    (res) => {
            return new Blob([res.blob()], { type: 'application/pdf' })
        }
}

Then, in order to get the file, you need to subscribe to it and you can create new ObjectURL and use window.open() to open PDF in new tab:

this.myService.downloadPDF().subscribe(
        (res) => {
        var fileURL = URL.createObjectURL(res);
        window.open(fileURL);
        }
    );
Stefan Svrkota
  • 40,477
  • 8
  • 90
  • 83
  • Hi,Stefan.It is showing me failed to to load PDF document.Please help me.I am using Angular4. – Mohit Jan 11 '18 at 05:05
  • I could able to download but not able to show in the new browser tab. – user1892203 Jan 19 '18 at 05:23
  • `return new Blob([res.blob()]` saved my day, Thanks – Shailendra Madda Jul 18 '18 at 13:51
  • 1
    Be careful if you're using an ad-blocker extension. Ad-blockers block blob URLs by default. As a result, e.g. in Chrome and Firefox, with the uBlock Origin extension, it would try to open the new window and close it automatically. You can read more about here: https://stackoverflow.com/questions/51272781/why-do-ad-blockers-block-blobs – AsGoodAsItGets Sep 11 '18 at 15:16
  • Also, if you care about this working in IE too, read this: https://stackoverflow.com/questions/24007073/open-links-made-by-createobjecturl-in-ie11 – AsGoodAsItGets Sep 11 '18 at 15:59
14

Angular v.5.2.1 answer:

In *.services.ts

downloadPDF(): any {
    return this._httpClient.get(url, { responseType: 'blob'})
            .map(res => {
            return new Blob([res], { type: 'application/pdf', });
        });
  }

And then in *.component.ts

downloadPDF() {
    let tab = window.open();
    this._getPdfService
      .downloadPDF()
      .subscribe(data => {
        const fileUrl = URL.createObjectURL(data);
        tab.location.href = fileUrl;
      });
  }

Its important to initiate and open a new tab before calling the service. Then set this tabs url to the fileurl.

jonas
  • 1,456
  • 2
  • 20
  • 27
  • 1
    why is important to open the tab before calling the service instead of opening it with the objecturl as parameter (as shown in the selected answer)? – Pau Fracés Feb 07 '18 at 18:52
  • 2
    @PauFracés because you're not 'allowed' to open a tab "programatically", only users are allowed to open tabs, thus you must initiate a new tab as close as possible to the user interaction which happens when a user click on a button which then calls `downloadPDF()`. Inside the subscription is too far from the user interaction. – jonas Feb 08 '18 at 08:36
  • 1
    I'm getting Error Failed to load PDF document. – Adam Mendoza Apr 06 '18 at 04:29
  • @jonas Can you take a look at this question. I have a similar question: https://stackoverflow.com/questions/55070184/download-pdf-automatically-after-getting-file-path-string-from-api-call – Euridice01 Mar 10 '19 at 22:24
5

ANGULAR 5

I had the same problem which I lost few days on that.

Here my answer may help others, which helped to render pdf.

For me even though if i mention as responseType : 'arraybuffer', it was unable to take it.

For that you need to mention as responseType : 'arraybuffer' as 'json'.(Reference)

Working code

service.ts

downloadPDF(): any {
return this._httpClient.get(url, { responseType: 'blob' as 'json' })
        .map(res => {
        return new Blob([res], { type: 'application/pdf', });
    });

}

component.ts

this.myService.downloadPDF().subscribe(
    (res) => {
    var fileURL = URL.createObjectURL(res);
    window.open(fileURL);
    }
);

Referred from the below link

https://github.com/angular/angular/issues/18586

MPPNBD
  • 1,225
  • 3
  • 15
  • 30
  • How do I change it for my service call? https://stackoverflow.com/questions/55070184/download-pdf-automatically-after-getting-file-path-string-from-api-call – Euridice01 Mar 10 '19 at 22:24
0

Angular 2+ Example PDF-viewer

Page.html

<div class="container">
<div>
    <label>PDF src</label>
    <input type="text" placeholder="PDF src" [(ngModel)]="pdfSrc">
</div>
<div>
    <label>Page:</label>
    <input type="number" placeholder="Page" [(ngModel)]="page">
</div>
<div class="row">
    <div class="col-md-5">
        <div class="thumbnail" style="width: 150px;height: 200px;" (click)="pdfShow=!pdfShow">
            <p>click me to view PDF in Iframe!</p>
            <pdf-viewer [src]="pdfSrc"
                        [page]="page"
                        [original-size]="false"
                        style="display: block;"
             ></pdf-viewer>
        </div>
        <br>
    </div>
    <div class="col-md-7">
        <div *ngIf="!pdfShow">
            <h4>PDF in Iframe</h4>
            <iframe width="500" height="600" [src]="pageurl" type="application/pdf"></iframe>
        </div>
    </div>
</div>
<br><br>
<h2> PDF in Object Tag</h2>
<object width="500" height="600"  data="https://vadimdez.github.io/ng2-pdf-viewer/pdf-test.pdf" type="application/pdf"></object>

page.ts

import { Component } from '@angular/core';
import { BrowserModule, DomSanitizer, SafeResourceUrl } from '@angular/platform- 
browser'

@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
 })
 export class AppComponent {

  pdfSrc = 'https://vadimdez.github.io/ng2-pdf-viewer/pdf-test.pdf';
  page: number = 1;
  pageurl: SafeResourceUrl;

  constructor(private domSanitizer: DomSanitizer) {
     }
      ngOnInit() {
      this.pageurl = this.domSanitizer.bypassSecurityTrustResourceUrl(this.pdfSrc);
     }
     title = 'Mohsen';
     }

app.module.ts

add

import { FormsModule } from '@angular/forms'; 
import { PdfViewerComponent } from 'ng2-pdf-viewer';
import { HttpModule } from '@angular/http';.
import {HttpClientModule} from '@angular/common/http';
import { BrowserModule } from '@angular/platform-browser';

import the

imports: [
    BrowserModule,
    HttpClientModule,
    HttpModule,
    FormsModule,
    RouterModule.forRoot(appRoutes)
],
cakan
  • 1,820
  • 5
  • 29
  • 33