【问题标题】:Electron: print iframe given reference to itElectron:打印 iframe 给定参考
【发布时间】:2021-10-15 11:23:27
【问题描述】:

我想使用 react-to-print 库从我的 Electron 应用程序中打印 iframe。如何使用iframe 引用来获取要打印的正确窗口/元素?

const handleElectronPrint = async (target: HTMLIFrameElement) {
  // Instead of this (printing the whole page)
  // let win = BrowserWindow.getFocusedWindow();

  // How do I print just the referenced iframe?
  // `target` iframe has id="printWindow", how to select it?
  let win = BrowserWindow.getMyIframe();
  
  // Is this the right way to do the print once we have the iframe?
  const options = { printBackground: true };
  win.webContents.print(options, (success, failureReason) => {
    if (!success) console.log(failureReason);
  
    console.log('Print Initiated');
  }); 
};

<ReactToPrint
 ...
 print={handleElectronPrint}
/>

【问题讨论】:

  • 尝试创建一个 BrowserWindow,并将 iframe 临时分配给它。然后打印并删除浏览器窗口?
  • @Base64__ 我对Electron一无所知,为什么我要问这个问题呵呵。如果您能提供一个工作示例,可能作为答案,将不胜感激

标签: javascript reactjs printing electron


【解决方案1】:

您需要将 iframe 对象转换为Data URL。并将 URL 加载到一个新的隐藏 BrowserWindow 对象中。
Renderer process 中构建数据URL,并使用preload 将URL 发送到主进程。在主进程中执行 BrowserWindow.loadURL 和打印。

App.js

  // Send print request to the Main process
  this.handlePrint = function (target) {
   return new Promise(() => {
    console.log('forwarding print request to the main process...');

    // convert the iframe into data url
    // https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs
    let data = target.contentWindow.document.documentElement.outerHTML;
    //console.log(data);
    var blob = new Blob([data], { type: 'text/html' });
    var url = URL.createObjectURL(blob);

    window.electronAPI.printComponent(url, (response) => {
     console.log('Main: ', response);
    });
   });
  };

ma​​in.js

// List of all options at -
// https://www.electronjs.org/docs/latest/api/web-contents#contentsprintoptions-callback
const printOptions = {
 silent: false,
 printBackground: true,
 color: true,
 margin: {
  marginType: 'printableArea',
 },
 landscape: false,
 pagesPerSheet: 1,
 collate: false,
 copies: 1,
 header: 'Page header',
 footer: 'Page footer',
};

ipcMain.handle('printComponent', (event, url) => {
 let win = new BrowserWindow({ show: false });
 win.loadURL(url);

 win.webContents.on('did-finish-load', () => {
  win.webContents.print(printOptions, (success, failureReason) => {
   console.log('Print Initiated in Main...');
   if (!success) console.log(failureReason);
  });
 });
 return 'done in main';
});

preload.js

const { contextBridge, ipcRenderer } = require('electron');

contextBridge.exposeInMainWorld('electronAPI', {
 printComponent: async (url, callback) => {
  let response = await ipcRenderer.invoke('printComponent', url);
  callback(response);
 },
});


这是所有print options 的列表。页面大小、边距、方向等一些选项可以在 CSS @page 规则中设置,请参考我的演示应用程序中的 App.css。

这是 GitHub 上的演示应用程序 electron-react-to-print-demo


打印预览:由于these reasons,没有Chrome浏览器风格的内置打印预览功能。我们需要实施我们自己的解决方法。喜欢打印到 PDF 并在新窗口中显示 pdf:

//handle preview
ipcMain.handle('previewComponent', (event, url) => {
 let win = new BrowserWindow({ title: 'Preview', show: false, autoHideMenuBar: true });

 win.loadURL(url);

 win.webContents.once('did-finish-load', () => {
  win.webContents.printToPDF(printOptions).then((data) => {
    let buf = Buffer.from(data);
    var data = buf.toString('base64');
    let url = 'data:application/pdf;base64,' + data;

    win.webContents.on('ready-to-show', () => {
     win.show();
     win.setTitle('Preview');
    });
    win.webContents.on('closed', () => win = null;);
    win.loadURL(url);

   })
   .catch((error) => {
    console.log(error);
   });
 });
 return 'shown preview window';
});

我在electron-react-to-print-demo中添加了上述预览功能。

【讨论】:

  • 这真是太棒了,正是我要找的,谢谢!一个快速跟进:有没有办法让 Electron 显示类似于浏览器的打印预览?
  • 不幸的是,他们没有使用 chromium 的打印 API。正如我在更新的答案中讨论的那样,所有人都建议在新窗口中显示打印的 pdf 的相同解决方法。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-10-20
  • 2018-10-23
  • 1970-01-01
  • 2011-09-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多