does_not_compute
does_not_compute

Reputation: 476

Node (Express) - Trying to save a PDF from an API call

I've tried all sorts to get this to work. I'm trying to request a PDF from an API on node, then send this back to the client who called it to begin with.

For the minute I just want to successfully save and view the PDF on the node server.

The issue is the PDF file is always empty when I open it (Even though it has a size of 30kb).

The basic flow is like this (removed a few bits, but the below code works and returns me the PDF fine)

// We pass through session ID's, request dates etc through in body
app.post("/getPayslipURL", function(client_request, res) {

    // create request, which will simply pass on the data to the database (In order to get the NI number we need for the pay API)
    const NI_NUMBER_REQUEST = db_api.createRequestTemplate({
        body: JSON.stringify(client_request.body)
    });

    // Create a chain of HTTPS Requests, Starting with our call to the DB
    requestPromise(NI_NUMBER_REQUEST)
        .then((db_response) => {   
            const PAY_API_OPTIONS = /*Code to generate options based on furhter DB info (Includes dates etc)*/
            return requestPromise(PAY_API_OPTIONS); // Call pay API
        })
        .then((pay_pdf_data) => { 

            console.log(typeof pay_pdf_data); // It's a string
            // At this point I can log pay_pdf_data, But if I try to save it to file it's always empty
            // No matter how I encode it etc

            fs.writeFile("./test.pdf", pay_pdf_data, 'binary', function(err) {
                if(err) {
                    return console.log(err);
                }
                console.log("The file was saved!");
            }); 

        })
        .catch(err => `Error caught: ${console.log}`) // Catch any errors on our request chain
    });
}

I've tried saving with / without the binary flag as suggested in other posts in both the file save aswell as within the requests itself. Also various types of decoding methods have been tried, I always get an empty PDF saved.

My return data looks like this (is much bigger, when saved as test.pdf I get a 30kb file as before mentioned)

%PDF-1.4 %���� 1 0 obj 0 obj <

I've found a post which says about piping the data all the way through, I have a feeling my pdf_data is corrupted when getting converted to a string

Any ideas how would I go about doing this with the current setup?

e/ RequestPromise is a library, could also use the standards request library if it's easier

https://github.com/request/request-promise - https://github.com/request/request

Thanks!

Upvotes: 2

Views: 3142

Answers (1)

GPX
GPX

Reputation: 3645

Your code doesn't work because the underlying request library (used by request-promise) requires the option encoding set to null for binary data - see https://github.com/request/request#requestoptions-callback.

Here's how you download binary data using that module -

app.post("/getPayslipURL", function(client_request, res) {
    const NI_NUMBER_REQUEST = db_api.createRequestTemplate({
        body: JSON.stringify(client_request.body),
        encoding: null
    });

    requestPromise(NI_NUMBER_REQUEST)
        .then((db_response) => {   
            const PAY_API_OPTIONS = /*Code to generate options based on furhter DB info (Includes dates etc)*/
            return requestPromise(PAY_API_OPTIONS); // Call pay API
        })
        .then((pay_pdf_data) => { 
            fs.writeFile("./test.pdf", pay_pdf_data, 'binary', (err) => {
                if(err) {
                    return console.log(err);
                }
                console.log("The file was saved!");
            }); 
        })
        .catch(err => `Error caught: ${console.log}`) // Catch any errors on our request chain
    });
}

Upvotes: 5

Related Questions