How to show images inline of code node output pane?

I have a working puppeteer js script which returns screenshots as downloadable images, but I would love to have them embedded like I’ve seen otherwise.

Here’s the last few lines of my js code trying what I would hope would work but did not:

        binary: {
          [binaryPropertyName]: {
            data: screenshotBase64,
            mimeType: 'image/png',
            fileExtension: 'png',
            fileName: binaryPropertyName,
            display: 'inline' //  Display the image within the GUI pane
          }

Hey @gzim,

Do you have a screenshot of what you are trying to achieve?

Here’s an example from a custom node for puppeteer. Hope I don’t have to implement any custom functions to get similar results from a Code Node

Hey @gzim,

That looks like an old n8n version but as long as n8n knows the data type it should just work when you click view. No need to add display: 'inline', Can you share what you currently see or the error you are getting?

Hi Jon,
Here’s two different methods I’ve tried with different results:

  1. with all optional binary metadata fields filled in, it shows option to download, but not view

  2. only file name and binary fields used, it shows only file name, no download or view options

Can you share the example workflow?

The workflow right now is just a single code node containing this script. I went a bit crazy sanitizing, so just know that the real code does work perfectly except that there is no previewing the pngs or pdfs, I must download them to view:

const puppeteer = require('puppeteer');

async function captureScreenshot(page) {
  return await page.screenshot({ encoding: 'base64' });
}

async function navigateAndWaitForNavigation(page, selector) {
  try {
    await Promise.all([
      page.click(selector),
      page.waitForNavigation({ waitUntil: 'networkidle2' }) // Adjust timeout as needed
    ]);
  } catch (error) {
    console.log(`Navigation error: ${error.message}`);
  }
}
//function for quickly adding screenshots to output item array
async function addItemWithScreenshot(items, page, filename) {
  const screenshot = await captureScreenshot(page);
  items.push(
{
  json:
    {
      filename: filename,
      size: screenshot.length
    },
    binary: {
      [filename]: {
        data: screenshot,
        mimeType: 'image/png',
        fileExtension: 'png',
        fileName: filename
      }
    }
  });
}


//define sleep function for explicit waiting
const sleep = ms => new Promise(r => setTimeout(r, ms));



//main process

return new Promise(async (resolve, reject) => {
  try {
    const browser = await puppeteer.launch({
      executablePath: '/usr/bin/chromium-browser',
      args: ['--no-sandbox', '--disable-setuid-sandbox', '--user-data-dir="/xxx/"'],
      headless: true
    });

    const url = 'xxx';
    const items = [];

    var page = await browser.newPage();
    await page.setViewport({ width: 1280, height: 800 });



    await page.goto(url, { waitUntil: 'networkidle2' });


    // take screenshot before submitting and nav away
    await addItemWithScreenshot(items, page, '1.png');
    
    // type email address into textbox
    await page.type('#email', 'xxx');
    
    // take screenshot before submitting and nav away
    await addItemWithScreenshot(items, page, 2.png');

    // click submit button and wait for nav
'''
    try {
      await navigateAndWaitForNavigation(page, '#xxx');
    } catch (error) {
      console.log(`Error during post email entry navigation: ${error.message}`);
    }

    // Type the password
    await page.waitForSelector('xxx');
    await page.type('xxx', 'xxx');
    // ss the filled in pw before submitting
    await addItemWithScreenshot(items, page, '3.png');
   // submit pw
    try {
      await navigateAndWaitForNavigation(page, 'xxx'); // Hitting Enter
      
    } catch (error) {
      console.log(`Error during password submit navigation: ${error.message}`);
    }

    // 2 FA page
    try {
      await Promise.all(
        [
          page.waitForSelector('[data-value="xxx"]'),
          addItemWithScreenshot(items, page, '4.png'),
          navigateAndWaitForNavigation(page, '[data-value="xxx"]' )
        ]
        )
        }
    catch (error) {
      console.log(`Error clicking element: ${error.message}`);
    }
   
    
    await addItemWithScreenshot(items, page, '5.png');


     try {
      await Promise.all(
        [
          page.click('[name="xxx"]'),
          navigateAndWaitForNavigation(page, '[id="xxx"]')
        ]
        )
        }
    catch (error) {
      console.log(`Error clicking element: ${error.message}`);
    }

    await addItemWithScreenshot(items, page, '6.png');

    await page.goto('xxx', { waitUntil: 'networkidle2' });

    await page.waitForSelector('[xxx]');
    
    await addItemWithScreenshot(items, page, '7.png');

    const reportelement = await page.$('[aria-label="xxx"]');

    const reportpdf = await page.pdf();

    const pcookies = await page.cookies();

    
  // Generate a PDF from the screenshot

  items.push(
    {
      json:
   {
      filename: 'report.pdf',
      size: reportpdf.length
    },
      binary: {
        ['report.pdf']: {
          data: reportpdf.toString('base64'),
          fileName: 'report.pdf',
          mimeType: 'application/pdf'
        }
    }
  });
    
    await page.close();
    await browser.close();

    // Resolve the promise with the items array
    resolve(items);
  } catch (error) {
    console.log(`Error in Puppeteer operation: ${error.message}`);
    reject(error);
  }
});

Hey @gzim,

It could be the encoding maybe, I don’t have a puppeteer image to hand but as it is just base64 data I can use that to test.