0

I am trying to download invoice from website using puppeteer, I just started to learn puppeteer. I am using node to create and execute the code. I have managed to login and navigate to the invoice page, but it opens in new tab, so, code is not detecting it since its not the active tab. This is the code I used:

const puppeteer = require('puppeteer')

const SECRET_EMAIL = 'emailid'
const SECRET_PASSWORD = 'password'

const main = async () => {
  const browser = await puppeteer.launch({
    headless: false,
  })
  const page = await browser.newPage()
  await page.goto('https://my.apify.com/sign-in', { waitUntil: 'networkidle2' })
  await page.waitForSelector('div.sign_shared__SignForm-sc-1jf30gt-2.kFKpB')
  await page.type('input#email', SECRET_EMAIL)
  await page.type('input#password', SECRET_PASSWORD)
  await page.click('input[type="submit"]')
  await page.waitForSelector('#logged-user')
  await page.goto('https://my.apify.com/billing#/invoices', { waitUntil: 'networkidle2' })
  await page.waitForSelector('#reactive-table-1')
  await page.click('#reactive-table-1 > tbody > tr:nth-child(1) > td.number > a')
  const newPagePromise = new Promise(x => browser.once('targetcreated', target => x(target.page())))
  const page2 = await newPagePromise
  await page2.bringToFront()
  await page2.screenshot({ path: 'apify1.png' })
  //await browser.close()
}

main()

In the above code I am just trying to take screenshot. Can anyone help me?

neenkart
  • 158
  • 2
  • 21
  • have you looked here? https://stackoverflow.com/questions/49245080/how-to-download-file-with-puppeteer-using-headless-true – Or Assayag Nov 21 '20 at 20:17
  • Note: Per Puppeteer v5.5.0 documentation, "Headless mode doesn't support navigation to a PDF document." https://pptr.dev/#?product=Puppeteer&version=v5.5.0&show=api-framegotourl-options https://bugs.chromium.org/p/chromium/issues/detail?id=761295 – intltechventures Nov 21 '20 at 20:30
  • You may need to use promise and .bringToFront(); See this posting for an example https://pocketadmin.tech/en/puppeteer-open-link-in-new-tab/ – intltechventures Nov 21 '20 at 20:37
  • Thank you guys, I have updated the code as per you guys suggestion, now I am able to keep the invoice tab in front and take a screenshot. But, i still dont know how to download the pdf file. – neenkart Nov 23 '20 at 19:23

1 Answers1

0

Here is an example of a work-around for the chromium issue mentioned in the comments above. Adapt to fit your specific needs and use-case. Basically, you need to capture the new page (target) and then do whatever you need to do to download the file, possibly pass it as a buffer to Node as per the example below if no other means work for you (including a direct request to the download location via fetch or ideally some request library on the back-end)

const [PDF_page] = await Promise.all([
    browser
        .waitForTarget(target => target.url().includes('my.apify.com/account/invoices/' && target).then(target => target.page()),
    ATT_page.click('#reactive-table-1 > tbody > tr:nth-child(1) > td.number > a'),
]);

const asyncRes = PDF_page.waitForResponse(response =>
    response
        .request()
        .url()
        .includes('my.apify.com/account/invoices'));

await PDF_page.reload();
const res = await asyncRes;
const url = res.url();
const headers = res.headers();

if (!headers['content-type'].includes('application/pdf')) {
    await PDF_page.close();
    return null;
}

const options = {
    // target request options
};

const pdfAb = await PDF_page.evaluate(
    async (url, options) => {
        function bufferToBase64(buffer) {
            return btoa(
                new Uint8Array(buffer).reduce((data, byte) => {
                    return data + String.fromCharCode(byte);
                }, ''),
            );
        }

        return await fetch(url, options)
            .then(response => response.arrayBuffer())
            .then(arrayBuffer => bufferToBase64(arrayBuffer));
    },
    url,
    options,
);

const pdf = Buffer.from(pdfAb, 'base64');
await PDF_page.close();
  • Thank you, I am pretty new to nodejs and I dont know how to use the code you provided, can you please check my updated code and see how your code can be used in my case. – neenkart Nov 23 '20 at 19:24
  • @neenkart Adapted the answer to better fit your use case. This should roughly work with your scenario. Let me know if you find a better solution :-) – Vasek Tobey Vlcek Dec 04 '20 at 08:55
  • Still didnt work, anyway thanks for the help :-). Still trying to figure out a method to fix it, will update here if I find a solution. – neenkart Dec 17 '20 at 11:49