Reputation: 857
I am working with a web API service (DocRaptor) that returns a PDF as the response. While initially working with the API, I was able generate a PDF and view the PDF on their site. I received a 200 Status Code telling me that the response was successful. However, the result of the post was still returned as an error on the Angular side using this code:
return this.http
.post("https://docraptor.com/docs", {
headers: {
"Content-Type": "application/json"
},
user_credentials: "WEB_API_KEY",
doc: {
test: true,
name: "testDocument.pdf",
document_content: documentContent,
type: "pdf"
}
})
.subscribe(
res => {
console.log(res);
},
err => {
console.log("Error occured: " + err);
}
);
I am assuming this is because the code was expecting JSON as a result, and instead the API returned a PDF.
Angular's documentation on Requesting non-JSON Data does not go into enough detail on how to consume the response using the HttpClient (and neither does DocRaptor's for that matter). When debugging, I can't tell (using the Network tab in Chrome) that the API call is even being sent, or a response returned, using the code below. This is likely a problem in the syntax below, but the following code is an approach I've tried using the documentation I know that's available:
return this.http
.post("https://docraptor.com/docs", {
responseType: "blob",
headers: {
"Content-Type": "application/json",
Accept: "application/pdf"
},
user_credentials: "WEB_API_KEY",
doc: {
test: true,
name: "testDocument.pdf",
document_content: documentContent,
type: "pdf"
}
})
.pipe(tap(data => this.downloadFile(data, "application/pdf")));
UPDATE:
I have rearchitected my code as suggested in the responses here. However, I am still receiving the original error, which is that I'm getting a 200 Status back from DocRaptor API, but Angular's HttpClient isn't parsing the response as a PDF. I've added in the headers to accept a PDF, and I still receive an error message that "Unexpected token % in JSON at position 0".
repl.component.ts
generatePdf() {
var htmlCard = this.cards.filter((card: Card) => card.language === "html")[0];
var cssCard = this.cards.filter((card: Card) => card.language === "css")[0];
var documentContent = this.generateCode(
htmlCard.editorContent,
cssCard.editorContent
);
this.docRaptorService.generatePdf(documentContent).subscribe(results => {
let blob = results;
let filename = "testDocument.pdf";
FileSaver.saveAs(blob, filename);
});
}
doc-raptor.service.ts
generatePdf(documentContent: string) {
return this.http
.post("https://docraptor.com/docs", {
headers: {
"Content-Type": "application/json",
Accept: "application/pdf"
},
user_credentials: "WEB_API_KEY",
doc: {
test: true,
name: "testDocument.pdf",
document_content: documentContent,
type: "pdf"
},
responseType: "blob"
})
.pipe(
tap(
data => console.log(documentContent, data),
error => console.log(documentContent, error)
)
);
}
Upvotes: 3
Views: 11177
Reputation: 367
I also had a similar need where my Api returned a Pdf file object. I first tried by passing headers object with "Accept" set as "Accept": "application/pdf". But that did not work.
Then I simply set "responseType" in httpOptions as:
this._httpClient.post(apiUrl, filterParams, { responseType: 'blob' });
and it worked.
Upvotes: 1
Reputation: 7437
.pipe(tap(data => this.downloadFile(data, "application/pdf")));
You have to subscribe
to an Observable
before it will do anything. The Angular example is returning the Observable
with a tap
operator 'attached' to it. Your own example is returning the Subscription
, which is useless to anything calling your method.
It's the recommended design pattern for Angular services; the service creates the Observable
, which is like a contract for a stream of work and data transformations, then the caller can subscribe
to it and get the result of the work.
Upvotes: 0