【问题标题】:Generate PDF with selenium chrome driver使用 selenium chrome 驱动程序生成 PDF
【发布时间】:2018-05-23 13:35:42
【问题描述】:

要从 HTML 文件生成 PDF,我想使用 selenium Chrome 驱动程序。

我用命令行试了一下:

chrome.exe --headless --disable-gpu --print-to-pdf   file:///C:invoiceTemplate2.html

而且效果很好,所以我想用 JAVA 来做,这是我的代码:

System.setProperty("webdriver.chrome.driver", "C:/work/chromedriver.exe");
ChromeOptions options = new ChromeOptions();
options.addArguments("--headless", "--disable-gpu", "--print-to-pdf",
            "file:///C:/invoiceTemplate2.html");
WebDriver driver = new ChromeDriver(options);
driver.quit();

服务器启动没有问题,但打开 chrome 时有多个选项卡,带有我在选项中指定的参数。

有什么解决办法吗?谢谢。

【问题讨论】:

  • --print-to-pdf 作为参数提供时浏览器会立即关闭,使用 Selenium 有什么意义?
  • @FlorentB.我没有完全理解你的意思
  • @MoatezBouhdid 您不能使用 selenium 将网页直接保存为 pdf。相反,您可以保存页面的屏幕截图,然后将其转换为 pdf,但这太昂贵了。作为一种解决方法,您可以编写 python 脚本或 bash 脚本来运行命令
  • 我为此添加了一个答案。请让我知道您的反馈
  • 嘿,找到解决办法了吗?

标签: java google-chrome selenium pdf selenium-webdriver


【解决方案1】:

这确实可以使用 Selenium 和 ChromeDriver(使用 Chrome 版本 85 测试)来完成,但是从 webdriver 启动 Chrome 时使用“打印到 PDF”选项不是解决方案。

要做的是使用ChromeDriver的命令执行功能:

https://www.selenium.dev/selenium/docs/api/java/org/openqa/selenium/remote/RemoteWebDriver.html#execute-java.lang.String-java.util.Map-

有一个名为Page.printToPDF 的命令提供PDF 输出功能。返回包含“数据”项的字典,生成的 PDF 为 base-64 编码格式。

很遗憾,我没有完整的 Java 示例,但是在这个答案中,有一个 C# 示例(Selenium 方法在 C# 中的命名与 Java 不同,但原理应该相同):

https://stackoverflow.com/a/63970792/2416627

Chrome 中的Page.printToPDF 命令记录在此:

https://chromedevtools.github.io/devtools-protocol/tot/Page/#method-printToPDF

【讨论】:

    【解决方案2】:

    更新: 我们注意到最初的解决方法并不总是正常工作,我们选择了 Selenium + ChromeDriver:

    public void generatePdf(Path inputPath, Path outputPath) throws Exception
    {
        try
        {
    
            ChromeOptions options = new ChromeOptions();
            options.addArguments("--headless", "--disable-gpu", "--run-all-compositor-stages-before-draw");
            ChromeDriver chromeDriver = new ChromeDriver(options);
            chromeDriver.get(inputPath.toString());
            Map<String, Object> params = new HashMap();
            
            String command = "Page.printToPDF";
            Map<String, Object> output = chromeDriver.executeCdpCommand(command, params);
    
            try
            {
                FileOutputStream fileOutputStream = new FileOutputStream(outputPath.toString());
                byte[] byteArray = java.util.Base64.getDecoder().decode((String) output.get("data"));
                fileOutputStream.write(byteArray);
                fileOutputStream.close();
            }
            catch (IOException e)
            {
                e.printStackTrace();
            }
        }
        catch (Exception e)
        {
            e.printStackTrace(System.err);
            throw e;
        }
    }
    

    如果这将被频繁调用,我建议重用驱动程序对象,因为它需要一段时间来初始化。

    记得关闭或退出驱动程序以避免留下 Zombie chrome 进程,还记得在你的机器上安装 ChromeDriver。


    原解决方案:

    无法使用 ChromeDriver 获得所需的结果,我的解决方法是从我的 Java 程序的命令行中调用 headless chrome。

    这适用于 Windows,但只需更改命令变量中使用的路径的内容,它也应该可以在 Linux 中运行。

    public void generatePdf(Path inputPath, Path outputPath) throws Exception {
    
        try {
                
            String chromePath = "C:/Program Files (x86)/Google/Chrome/Application/chrome.exe";
            String command = chromePath + " --headless --disable-gpu --run-all-compositor-stages-before-draw --print-to-pdf=" + outputPath.toString() + " " + inputPath.toString();
                    
            // Runs "chrome" Windows command
            Process process = Runtime.getRuntime().exec(command);
            process.waitFor(); // Waits for the command's execution to finish 
                
        }catch (Exception e){
            
            e.printStackTrace(System.err);
            throw e;
    
        }finally{
            
            // Deletes files on exit
            input.toFile().deleteOnExit();
            output.toFile().deleteOnExit();
    
        }
    }
    

    注意:输入和输出路径都是使用 NIO 创建的临时文件。

    【讨论】:

      【解决方案3】:

      代码将帮助您在 Selenium c# 上以 PDF 格式保存页面

      using OpenQA.Selenium;
      using OpenQA.Selenium.Chrome;
      
          protected void PDFconversion(ChromeDriver driver, string root, string rootTemp)
          {
              //Grid.Rows.Add(TxtBxName.Text, TxtBxAddress.Text);
              try
              {
                  IJavaScriptExecutor js = (IJavaScriptExecutor)driver;
                  Thread.Sleep(500);
                  js.ExecuteScript("setTimeout(function() { window.print(); }, 0);");
                  Thread.Sleep(500);
                  driver.SwitchTo().Window(driver.WindowHandles.Last());
                  Thread.Sleep(500);
                  string JSPath = "document.querySelector('body>print-preview-app').shadowRoot.querySelector('#sidebar').shadowRoot.querySelector('#destinationSettings').shadowRoot.querySelector('#destinationSelect').shadowRoot.querySelector('print-preview-settings-section:nth-child(9)>div>select>option:nth-child(3)')";
                  Thread.Sleep(500);
                  IWebElement PrintBtn = (IWebElement)js.ExecuteScript($"return {JSPath}");
                  Thread.Sleep(500);
                  PrintBtn.Click();
                  string JSPath1 = "document.querySelector('body>print-preview-app').shadowRoot.querySelector('#sidebar').shadowRoot.querySelector('print-preview-button-strip').shadowRoot.querySelector('cr-button.action-button')";
                  Thread.Sleep(1000);
                  IWebElement PrintBtn1 = (IWebElement)js.ExecuteScript($"return {JSPath1}");
                  PrintBtn1.Click();
                  Thread.Sleep(1000);
                  SendKeys.Send("{HOME}");
                  SendKeys.Send(rootTemp + "\\" + "result.pdf"); // Path
                  SendKeys.Send("{TAB}");
                  SendKeys.Send("{TAB}");
                  SendKeys.Send("{TAB}");
                  SendKeys.Send("{ENTER}");
                  Thread.Sleep(1000);
             
              }
              catch (Exception ex){}
          }
      

      【讨论】:

        【解决方案4】:

        你必须做两件事。

        首先:使用 selenium 制作屏幕截图。

        第二:使用任何 pdf 工具转换该屏幕截图,例如 itext。这里我展示了一个完整的例子来说明如何做到这一点。

        第 1 步:从here 下载 itext 的 jar 并将该 jar 文件添加到您的构建路径。

        第 2 步:将此代码添加到您的项目中。

        ChromeOptions options = new ChromeOptions();
        options.addArguments("disable-infobars");
        options.addArguments("--print-to-pdf");
        
        WebDriver driver = new ChromeDriver(options);
        driver.get("file:///C:/invoiceTemplate2.html");
        
        try {
            File screenshot = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
            FileUtils.copyFile(screenshot, new File("screenshot.png"));
            Document document = new Document(PageSize.A4, 20, 20, 20, 20);
            PdfWriter.getInstance(document, new FileOutputStream("webaspdf.pdf"));
            document.open();
            Image image = Image.getInstance("screenshot.png");
            document.add(image);
            document.close();
        }
        catch (Exception e2) {
            // TODO Auto-generated catch block
            e2.printStackTrace();
        }
        

        注意:要使用提到的 itext 包,请将所需的导入添加到您的代码中。

        import com.itextpdf.text.Document;
        import com.itextpdf.text.Image;
        import com.itextpdf.text.PageSize;
        import com.itextpdf.text.pdf.PdfWriter;
        import org.apache.commons.io.FileUtils;
        import org.openqa.selenium.OutputType;
        import org.openqa.selenium.TakesScreenshot;
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-03-10
          • 2022-01-28
          • 1970-01-01
          • 2011-09-16
          • 2014-04-03
          • 2022-06-22
          相关资源
          最近更新 更多