Request Application/PDF generating file with wrong information[Angularjs+Nodejs]

Asked

Viewed 868 times

0

I have an Angularjs+Node(Express) application totally Restless. The back end only serves to validate requests and route to other applications, holders of business rules.

At some point, my front sends a request to generate a pdf, something like:

const callbackSucesso = function(resposta){                    
    if(resposta && resposta.data){
        let headers = resposta.headers();
        let blob = new Blob([resposta.data],{type: headers['content-type']} );
        saveAs(blob, "download.pdf");
    }else{
       //coisas que não importam aqui
    }
};
$http({
    method: 'POST',
    url: '/api/pdf',
    data: JSON.stringify(dto)
}).then(callbackSucesso,callbackErro);

However, when I open the generated file, I notice that there is information that is distorted, for example: DESCRIPTION => Description ¿½ï¿½

When performing by Postman, the return of the API is normally generated as a file.

I’ve found answers that talk to add type information to the Blob object - like this: Generate angular pdf using javascript - but the error remained.

When I tried to do it in the back end, the exits weren’t that different. Then I thought I’d intercept the Ode, generate the file, and redirect to the front.

   const fs = require('fs');
   ...
   request(options, function(error, resposta, corpo){
        if(error) {
           //não interessa para o contexto
        }else{
            fs.writeFileSync("10111.pdf", corpo,'binary');
           //aqui eu enviaria o link pro front baixar
        }
        next();
    }); 

I followed that example here: https://stackoverflow.com/questions/31040014/how-to-save-pdf-in-proper-encoding-via-nodejs

From now on I thank those who can clear my road(!)

1 answer

0

I found the solution in the following way:

In the back-end, which as I commented was just a router, I chose to change it to that endpoint, so as to receive the request that it redirects in the following way:

    //Gero minha requisição
        let options = gerarRequisicao("POST", endpointASerRedirecionadaARequest, req);
    //Crio um array para ir concatenando os valores recebidos via stream
        let pdf_buffer = []; 
    //Callback que será invocado ao completar a request. Observe que não utilizo o "body" que é fornecido, e sim o que  fui armazenando 
        const aoCompletar = (resposta,body) => { 
            // Aqui, concateno todos os valores que foram bufferizados.
            let data = Buffer.concat(pdf_buffer);
            resp.status(resposta.statusCode).json(data.toString('base64'));
        };

        request(options)
 /*Cada parte que recebo do meu stream, será adicionada no meu buffer, 
   que será utilizado no callback aoCompletar*/
            .on("data", d => pdf_buffer.push(d) )
            .on("complete", aoCompletar)
            .on("error", e => resp.status(500).json(geraMensagemDeErro(e)) );
        });

It seems to me that the value that is received as the "body" of the request via parameters in the callback used at the time of the question, it seems that it was incomplete, or something like that.

I took the liberty of sending back to front as Base64 to ensure how my requests will go.

On the front, when receiving the answer, convert the body to an array, play in a blob and download:

const callbackSucesso = function(resposta){                    
    if(respostaEstaValida(resposta)){
        let cabecalho = resposta.headers();
        let arquivo = converterBase64ParaBlob(resposta.data, cabecalho['content-type']);
        saveAs(arquivo, "download.pdf");
    }else{
        //não interessa para o contexto
    }
};
$http({        
    method: 'POST',
    url: `/api/pdf`,
    data: JSON.stringify(dto)
}).then(callbackSuceso,callbackErro);     

Finally, the conversion takes place as follows::

function converterBase64ParaBlob(base64, contentType){
    let respostaBruta = window.atob(base64);
    let tamanhoDaResposta = raw.length;
    let cache = new Uint8Array(new ArrayBuffer(tamanhoDaResposta ));
    for(let i = 0; i < rawLength; i++) {
        cache[i] = respostaBruta.charCodeAt(i);
    }
    let blob = new Blob([cache],{type: contentType} );
    return blob;
  }

Browser other questions tagged

You are not signed in. Login or sign up in order to post.