0

In my Angular4 Application, I call my Webservice which returns a response with ByteArrayContent. When I check this data in the network payload, it looks very much like a valid PDF-file. The html-string, from which the following data is generated, is valid for sure, because an online pdf converter (third party) is able to convert my html-string properly.

Generated data from the WebApi to prove it is a PDF-file

%PDF-1.5
4 0 obj
<</Type /Page/Parent 3 0 R/Contents 5 0 R/MediaBox [0 0 612 792]/Resources
<</Font<</FAAAAH 7 0 R>>>>/Group 
...
<</Length 9 0 R/Filter /FlateDecode>>stream
... ... ...
startxref
23589
%%EOF
  1. When I copy/paste this whole text into a txt-file and change the ending to .pdf, the file opens, but there is nothing displayed as it should

  2. When I use the JavaScript file-saver, the file gets downloaded. But the header and footer of the pdf-file provided is full with nul-values and it can't even be opened anymore.

This is code for downloading the file

` let myHeaders = new Headers({ 
        'Content-Type': 'application/json',
        'Cache-Control': 'no-cache',
        'Accept': 'application/pdf',
        'Access-Control-Allow-Origin': '*' });
    let options = new RequestOptions({ headers: myHeaders });
    return this.http.post(this.URL, {'htmlString':html}, options)
    .map((response: Response) => {
        let fileBlob:ArrayBuffer = response.arrayBuffer();
        let blob = new Blob([fileBlob], {type: 'application/pdf'});
        let filename = "testPdf.txt";
        FileSaver.saveAs(blob, filename);
        return response;
    });
}`

In the tutorial, they use response.blob() not response.arrayBuffer(), but when I use .blob(), the exception

Error: The request body isn't either a blob or an array buffer

Is there any way in Angular2+, TypeScript or JavaScript, to convert the PDF-data the right way?

This is my C# code, this should usually be fine. The HtmlToPdfServiceClient-Class is generated by a WSDL-file, so this part is definitely right

HtmlToPdfServiceClient client = new HtmlToPdfServiceClient();
HtmlToPdfConversionRequest reqest = new HtmlToPdfConversionRequest();
reqest.Format = ResponseFormats.BASE64;
reqest.InputText = Convert.ToBase64String(System.Text.Encoding.Unicode.GetBytes((string)json["htmlString"]));           
HtmlToPdfConversionResponse response = client.Conversion(reqest);        
HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK);
result.Content = new ByteArrayContent(Convert.FromBase64String(response.ResultBase64));          
result.Content.Headers.ContentType =
      new MediaTypeHeaderValue("application/pdf");           
client.Close();
return result;
  • Hi can you try to set in the RequestOptions the ResponseType to Blob – alfredson Mar 15 '18 at 10:04
  • let options = new RequestOptions({ headers: headers, responseType: ResponseContentType.Blob }); i tried this, but this class in unavailable or rather depracated –  Mar 15 '18 at 10:08
  • ok you are right, this works, but it's regretably deprecated. And it works just kindof. Within the PDF-file, the BASE64 data is displayed –  Mar 15 '18 at 10:15
  • I will post my code as an answer. it is too long for a comment – alfredson Mar 15 '18 at 10:31

2 Answers2

1

I implemented this a long time ago in our Angular Application and it works perfectly for me.

You will need to have the following dependencies in your component:

import * as FileSaver from 'file-saver'; import { Http, RequestOptions, Headers, ResponseContentType } from '@angular/http';

And the constructor of your component:

constructor(private http: Http) {}

All the following code can be wrapped in a method and can be triggered with a button click:

  1. Setup url with authorization header

const url = 'your/url/to/the/pdf'; const header = new Headers(); header.append('Authorization', 'your-authorization-token');

  1. Create Request Options with the header

const requestOptions = new RequestOptions({ headers: header });

  1. Add ResponseContentType to your Request Options

requestOptions.responseType = ResponseContentType.Blob;

  1. Getting your data from your API and save it with filesaver

this.http.get(url, requestOptions).subscribe(response => FileSaver.saveas(response.blob(), 'test.pdf'));

alfredson
  • 241
  • 1
  • 6
  • Yes it works with this solution. But i had a mistake in my C# code to, hard to find, but in combination with this, it's fine. I'm just struggling a bit with working with deprecated libraries, but it will do it for now –  Mar 15 '18 at 11:04
0

Are you getting HTML and want to convert it to PDF? If so, try some other api for converting HTML to PDF. I recommend to have a look on "ByteScout PDF SDK". It has very simple and straight forward way to do so. you can see the code snippet.

 // Create converter instance
            using (HtmlToPdfConverter converter = new HtmlToPdfConverter())
            {
                // Perform conversion
                converter.ConvertHtmlToPdf("sample.html", "result.pdf");
            }

            // Open result document in default PDF viewer
            Process.Start("result.pdf");
  • This looks nice, but after generating this, i have to give it to my frontend, and i think, this would result in the same problem –  Mar 15 '18 at 10:17
  • Please see the below post. https://stackoverflow.com/questions/291813/recommended-way-to-embed-pdf-in-html – Raheel Ahmad Mar 15 '18 at 12:57
  • Also please go through the documentation of SDK, you will find out some more things which might helps you in future as well. http://cdn.bytescout.com/help/BytescoutPDFSDK/index.html?_ga=2.9091253.1457732165.1522008970-62881910.1507833269 – Raheel Ahmad Mar 26 '18 at 04:33