AngularJS encounters an issue while attempting to print a PDF file

I am encountering an issue with printing a PDF file that was generated using reportViewer in my Web API. The browser displays an error when attempting to open the PDF file.

Below is the code snippet from the controller in my Web API:

// ...generate candidatosDataSet
LocalReport relatorio = new LocalReport();
string rootPath = HttpRuntime.AppDomainAppPath;
relatorio.ReportPath = rootPath + @"\Reports\Report.rdlc";

relatorio.DataSources.Add(new ReportDataSource("Candidatos", candidatosDataSet));
relatorio.Refresh();

byte[] relatorioBytes = ExportUtils.GerarArquivoPDF(relatorio);

response = Request.CreateResponse(HttpStatusCode.OK, relatorioBytes);
response.Content.Headers.ContentDisposition = System.Net.Http.Headers.ContentDispositionHeaderValue.Parse("attachment; filename=relatorio.pdf");
response.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/pdf");

This is how I generate the PDF File using reportViewer:

public static byte[] GerarArquivoPDF(LocalReport relatorio)
{
    String reportType = "PDF";
    String mimeType;
    String encoding;
    String fileNameExtension;
    String deviceInfo;
    Warning[] warnings;
    string[] streams;
    byte[] renderedBytes;

    deviceInfo = "<DeviceInfo>" + "  <OutputFormat>" + reportType + "</OutputFormat>" + "</DeviceInfo>";

    renderedBytes = relatorio.Render(
    reportType,
    deviceInfo,
    out mimeType,
    out encoding,
    out fileNameExtension,
    out streams,
    out warnings);

    return renderedBytes;
}

Here is the method from my AngularJS service:

function obterTermoConfirmacaoCandidatura(candidatoId) {
    return $http.get(configValues.baseUrl + 'candidato/GetRelatorio', 
    { 
        params: { candidatoId: candidatoId },
        responseType: 'arraybuffer'
    });
}

And here is the code snippet used to print the file in the AngularJS controller:

function imprimirTermoConfirmacaoCandidatura(id) {
    CandidatoAPIService.obterTermoConfirmacaoCandidatura(id).then(function (response) {

        var contentType = response.headers('Content-Type') || "application/octet-stream";

        var file = new Blob([response.data], {
            type: contentType
        });

        var fileUrl = URL.createObjectURL(file);
        var printWindow = $window.open(fileUrl);
        printWindow.print();

    }, function (error) {
        alert(error.data);
    });
}

Answer №1

The Web API was sending the response as a string enclosed in double quotes, causing issues with rendering the PDF File. To resolve this, I converted the server response to base64 using the following method:

 function convertToBlobFromBase64(base64Data, type) {

            var chunkSize = 512;
            base64Data = base64Data.replace(/"/g, '');
            base64Data = base64Data.replace(/^[^,]+,/, '');
            base64Data = base64Data.replace(/\s/g, '');

            var byteCharacters = window.atob(base64Data);
            var byteArrays = [];

            for (var offset = 0; offset < byteCharacters.length; offset += chunkSize) {
                var chunk = byteCharacters.slice(offset, offset + chunkSize);

                var byteNumbers = new Array(chunk.length);
                for (var i = 0; i < chunk.length; i++) {
                    byteNumbers[i] = chunk.charCodeAt(i);
                }

                var byteArray = new Uint8Array(byteNumbers);

                byteArrays.push(byteArray);
            }

            var blob = new Blob(byteArrays, { type: type });
            return blob;
        }

I updated the AngularJS controller to utilize this method for converting the response to base64:

function printImageUsageAuthorization() {
            CandidateAPIService.getImageUsageAuthorization()
            .then(function (response) {
                var contentType = response.headers('Content-Type') || "application/octet-stream";
                var file = UtilityService.convertToBlobFromBase64(response.data, "application/pdf");

                var fileUrl = URL.createObjectURL(file);
                var printWindow = $window.open(fileUrl);
                printWindow.print();
            }, function (error) {
                alert(error.data);
            });
        }

I also removed the responseType from the AngularJS service:

function getApplicationConfirmationLetter(candidateId) {
            return $http.get(configValues.baseUrl + 'candidate/GetApplicationConfirmationLetter', 
            {   
                params: { candidateId: candidateId }
            });
        }

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

How is it possible for TypeScript to enable the importing of dependencies that it ultimately cannot utilize during runtime?

Take a look at my sample project by following this link: https://github.com/DanKaplanSES/typescript-stub-examples/tree/JavaScript-import-invalid I have developed a file named main.ts: import uuid from "uuid"; console.log(uuid.v4()); While type ...

Using the onclick attribute as a unique identifier for a button

I am currently facing a challenge with a form that does not have an ID Here is the code snippet in question: <button class="btn btn-primary" onclick="showModal()" type="button">Browse Data</button> Unfortunately, I don't have any contro ...

Select the appropriate x64 or x86 version of the assembly based on the bitness of the referencing application

I have encountered a challenge with two assemblies that share the same namespace and classes. One is specifically designed for 32-bit systems, named assembly_x86.dll, while the other caters to 64-bit systems and is called assembly_x64.dll. My goal is to d ...

What are the benefits of using default ES module properties for exporting/importing compared to named module properties?

Currently studying the Material UI documentation, I came across this statement: It is noted in the example above that we used: import RaisedButton from 'material-ui/RaisedButton'; instead of import {RaisedButton} from 'material-ui&apo ...

Utilizing Jquery to locate a specific word within a sentence and then appending a span element around

I need help fixing a function that is supposed to find a specific word in a sentence and add a span element around it. Here is the code I have so far, but for some reason it's not working as expected. Can anyone spot the mistake? Thank you! ...

What is the best way to remove a component from MongoDB after a specified period of time has passed

I am currently working on a basic web application using Node.js and MongoDB. I'm struggling with deleting entries from this field: shows what my webpage looks like After entering some data and clicking the button, it creates a new collection in my Mo ...

Error: Attempting to access the 'body' property of an undefined object following a POST request in a MEAN application

Currently, I am attempting to send POST data from AngularJS to Express. My approach involves using curl to transmit the POST content. After sending the data and receiving a 200 response, I encounter an issue when trying to access the data through body-par ...

The CSS and JS codes are not successfully integrating into the webpage

I am encountering an issue with loading CSS and JS files onto my page. My project involves PHP and Xampp. The file structure is as follows: My Site - CSS - index.css - JS - index.js - Index.php (Apologies for the lack of a folder tre ...

A node module designed to efficiently convert multiple TIFF images into a single multipage TIFF document

Looking to combine several tiff images into a single file using nodejs/javascript. Is there a method to create a single tiff file with multiple pages from separate tiff images in nodejs? Can we convert a multi-page pdf into one tiff image using nodejs? ...

What is the best way to sequentially invoke an asynchronous function within an Observable method?

Presently, I have the following method: public classMethod( payload: Payload, ): Observable<Result> { const { targetProp } = payload; let target; return this.secondClass.secondClassMethod({ targetProp }).pipe( delayWhen(() ...

displaying the local path when a hyperlink to a different website is clicked

fetch(www.gnewsapi.com/news/someID).then(response => newsurl.href = JSON.stringify(data.articles[0].url) fetch('https://gnews.io/api/v3/search?q=platformer&token=642h462loljk').then(function (response) { return response.json(); }).th ...

Refreshing a webpage using AJAX from a different URL of a secondary web service

I am working on a page that retrieves data from a specific web service URL. I am conducting some processing involving a multiple choice checkbox, and I want the same page to reload and fetch its data from a second web service with a different URL to retrie ...

Updating to a newer version of jQuery causes issues with pop-out submenus

Looking for a way to create a menu with pop-out submenus? Here's an example using jQuery: <script type="text/javascript"> $(document).ready(function() { var hoverAttributes = { speed: 10, delay: 1 ...

When implementing javascript_pack_tag in Rails, an EOFError may occur

It seems like the files in public/packs/js are having trouble loading. Here are the javascript tags being used in the view: = javascript_include_tag 'application' = javascript_pack_tag 'application' The error displayed in the browser ...

Unexpected behavior from vuelidate triggered on blur

I have implemented vuelidate for form validation. My goal is to validate user input either when they move to the next input field or click outside of the current one. <div class="form-group col-md-6" :class="{invalid: $v.partner.email.$ ...

Updating Select Options Disabled/Enabled in Angular 2

In my Angular2 project, I have 2 select elements: <div ng-controller="ExampleController"> <form name="myForm"> <label for="companySelect"> Company: </label> <select name="companySelect" id= ...

Conceal an item if it is located past a certain point (from the viewpoint of the camera)

In the realm of three-dimensional space, imagine a cube represented by a THREE.Mesh that has been added to the scene. cube.position.set( 10, 10, 10 ); scene.add( cube ); Once you have rotated the scene using your mouse, the goal is to cleverly conceal th ...

Modifying an item within an array of Mongoose models

I am working with a model schema that looks like this: { _id: foo cart: { items: [ { id: number name: string, } ] } } My goal is to locate the document by its id and then modify the name value of the object in ...

Transferring data between Javascript and PHP with AJAX and JQuery

I'm currently working on a basic web page that involves sending data from an HTML page to a PHP script and receiving some data back. My approach involves using AJAX, but for some reason, the PHP script doesn't seem to execute at all. Here's ...

What is the best way to transfer JavaScript if conditions to an external file?

I am currently working on a script to transfer data between various software applications. Within this script, there is an if condition set up to ignore specific fields that are not required for the transfer process. The condition in question looks somethi ...