{"id":18634946,"url":"https://github.com/aoju/lancia","last_synced_at":"2025-04-11T07:33:41.664Z","repository":{"id":37110030,"uuid":"200366295","full_name":"aoju/lancia","owner":"aoju","description":"网页转PDF渲染服务。提供收据、发票、报告或任何网页内容转PDF的微服务","archived":false,"fork":false,"pushed_at":"2023-12-05T22:12:55.000Z","size":782,"stargazers_count":116,"open_issues_count":2,"forks_count":13,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-03-25T11:38:08.797Z","etag":null,"topics":["chrome","chrome-headless","chrome-node","lancia","pdf","puppeteer","screenshot"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/aoju.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-08-03T11:12:29.000Z","updated_at":"2024-10-21T01:51:12.000Z","dependencies_parsed_at":"2024-11-07T05:36:42.791Z","dependency_job_id":null,"html_url":"https://github.com/aoju/lancia","commit_stats":null,"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aoju%2Flancia","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aoju%2Flancia/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aoju%2Flancia/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aoju%2Flancia/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/aoju","download_url":"https://codeload.github.com/aoju/lancia/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248358919,"owners_count":21090448,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["chrome","chrome-headless","chrome-node","lancia","pdf","puppeteer","screenshot"],"created_at":"2024-11-07T05:22:44.804Z","updated_at":"2025-04-11T07:33:37.954Z","avatar_url":"https://github.com/aoju.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n\t\u003ca target=\"_blank\" href=\"https://www.mit-license.org\"\u003e\n\t\t\u003cimg src=\"https://img.shields.io/badge/license-MIT-green.svg\"\u003e\n\t\u003c/a\u003e\n\t\u003ca target=\"_blank\" href=\"https://nodejs.org\"\u003e\n\t\t\u003cimg src=\"https://img.shields.io/badge/node-%3E=8.0.0-brightgreen.svg\"\u003e\n\t\u003c/a\u003e\n\t\u003ca target=\"_blank\" href=\"https://www.npmjs.com\"\u003e\n\t\t\u003cimg src=\"https://img.shields.io/badge/npm-%3E=7.0.0-green.svg\"\u003e\n\t\u003c/a\u003e\n\t\t\u003ca target=\"_blank\" href=\"https://eslint.org\"\u003e\n\t\t\u003cimg src=\"https://img.shields.io/badge/eslint-%5E3.0.0-blue.svg\"\u003e\n\t\u003c/a\u003e\n\t\u003ca target=\"_blank\" href=\"https://travis-ci.org/aoju/lancia\"\u003e\n\t\t\u003cimg src=\"https://travis-ci.org/aoju/lancia.svg?branch=master\"\u003e\n\t\u003c/a\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n\t-- QQ群：\u003ca href=\"https://shang.qq.com/wpa/qunwpa?idkey=17fadd02891457034c6536c984f0d7db29b73ea14c9b86bba39ce18ed7a90e18\"\u003e839128\u003c/a\u003e --\n\u003c/p\u003e\n\n---\n\n## Lancia\n\n\u003e 网页转PDF渲染服务。提供收据、发票、报告或任何网页内容转PDF的微服务\n\n\n**⚠️ 警告 ⚠️** *请不要将这个API服务公开与互联网,除非你是知道潜在的风险.\n因为它允许用户在服务器上的Chrome会话中运行任何JavaScript代码,后果请自行负责*\n\n\n**⭐️ 特性:**\n\n* 将任何URL或HTML内容转换为PDF文件或图像(PNG/JPEG)\n* *使用[Puppeteer](https://github.com/GoogleChrome/puppeteer)渲染无头Chrome。PDF文件与桌面Chrome生成的文件一致.\n* 合理的默认值，大部分参数都是可配置的\n* 单页app (SPA)支持。在呈现之前，等待所有网络请求完成\n* Easy deployment to Heroku. We love Lambda but...Deploy to Heroku button.\n* 呈现延迟加载的元素 *(scrollPage 选项)*\n* 支持可选的“X-Access-Token”身份验证*\n\n\n* 默认情况下页面的 `@media print` CSS 规则将被忽略.将Chrome设置为模拟 `@media\n  screen`，使默认的pdf文件看起来更像实际站点。要获得更接近桌面Chrome的结果，请添加`\u0026emulateScreenMedia=false`查询参数。更多信息请访问[Puppeteer API docs](https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#pagepdfoptions).\n  API文档。\n  \n* Chrome启动时带有`--no-sandbox--disable-setuid-sandbox`标志，开启debian支持.\n\n* 如果服务器没有足够的内存，超大页面加载可能会导致Chrome崩溃.\n\n\n\n**为什么做这个服务?**\n\n当您需要自动生成PDF文件时，此微服务非常有用,不管出于什么原因。这些文件可以呈现为收据，周报，发票，或任何内容。\n\nPDF可以以多种方式生成，但其中难点之一是转换HTML+CSS,大部分工具无法呈现期望的结果，这个服务就是弥补不足才做的。\n\n\nTarget | Good | Deficiency | Link| Style\n----------|------|---------|------------| --------\njsPDF|整个过程在客户端执行(不需要服务器参与)，调用简单|生成的pdf为图片形式，且内容失真|N|Y\niText|1、功能基本可以实现，比较灵活2、生成pdf质量较高|1、对html标签严；格，少一个结束标签就会报错；2、后端实现复杂，服务器需要安装字体；3、图片渲染比较复杂(暂时还没解决)|Y|N\nwkhtmltopdf|1、调用方式简单(只需执行一行脚本)；2、生成pdf质量较高|1、服务器需要安装wkhtmltopdf环境；2、根据网址生成pdf，对于有权限控制的页面需要在拦截器进行处理|Y|N\n\n## API介绍\n\n要理解API选项，需要了解[Puppeteer](https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md)\n谷歌官方 Chrome node库。 这个API在内部使用。(\n用来渲染html代码)(https://github.com/aoju/lancia/blob/nodejs/src/app/shared/utils/render.utils.class.js)\n\n很简单，来看看。渲染流程::\n\n1. **`page.setViewport(options)`** 其中选项与 `viewport.*`匹配.\n2. *默认* **`page.emulateMedia('screen')`** 选项与 `emulateScreenMedia=true` 匹配使用.\n3. 渲染 URL **或** html.\n\n   如果定义了“url”，则调用 **`page.goto(url,options) `**，选项匹配' goto.* '。\n   否则,会从请求体获取html的地方调用 **`page.setContent(html, options)`** ，选项匹配' goto.* '。\n\n4. *默认* **`page.waitFor(num)`** 等待时间为： `waitFor=1000`.\n5. *默认* **`scrollPage=true`** 在页面渲染前会设置相关属性，如只需要第一页即可设置为false.\n\n    如果您想呈现一个延迟加载元素的页面，这个参数非常有用。\n\n6. 渲染输出\n\n  * 如果输出是 `pdf` 则使用 **`page.pdf(options)`** 完成输出,其中选项与`pdf.*`匹配.\n  * 如果输出是 `screenshot` 则使用 **`page.screenshot(options)`** 完成输出，其中选项与 `screenshot.*`匹配.\n\n### GET/POST /router/rest\n\n所有选项都作为查询参数传递。\n\n参数名称匹配[Puppeteer options](https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md)。\n\n这些选项与它的“POST”对应项完全相同，但是选项不同\n\n用点符号表示。如。”? pdf。scale=2 '而不是' {pdf: {scale: 2}} '。\n\n唯一需要的参数是“url”。\n\n\nParameter | Type | Default | Description\n----------|------|---------|------------\nurl | string | - | URL渲染PDF。(必需)\noutput | string | pdf | 指定输出格式。可选值: `pdf` 、 `screenshot`.\nemulateScreenMedia | boolean | `true` | 模拟 `@media screen` 渲染 PDF.\nignoreHttpsErrors | boolean | `false` | 忽略https错误.\nscrollPage | boolean | `false` | 启用滚动页面触发延迟加载元素，可选值： `true` 、 `false`.\nwaitFor | number | - | 延迟加载超时时间.\nattachmentName | string | - | 设置 `content-disposition` 确保浏览器下载属性,按照给定的字符串作为下载名称.\nviewport.width | number | `1600` | 预览宽度.\nviewport.height | number | `1200` | 预览高度.\nviewport.deviceScaleFactor | number | `1` | 设备比例信息.\nviewport.isMobile | boolean | `false` | 是否考虑移动端支持.\nviewport.hasTouch | boolean | `false` | 是否支持触摸.\nviewport.isLandscape | boolean | `false` | 是否考虑横屏模式.\ncookies[0][name] | string | - | Cookie 名称 (必需)\ncookies[0][value] | string | - | Cookie 值 (必需)\ncookies[0][url] | string | - | Cookie URL\ncookies[0][domain] | string | - | Cookie 域名\ncookies[0][path] | string | - | Cookie 路径\ncookies[0][expires] | number | - | Cookie 过期时间\ncookies[0][httpOnly] | boolean | - | Cookie httpOnly\ncookies[0][secure] | boolean | - | Cookie 安全\ncookies[0][sameSite] | string | - | `Strict` or `Lax`\ngoto.timeout | number | `30000` | 最大超时时间(毫秒)，默认为30秒，通过0禁用超时.\ngoto.waitUntil | string | `networkidle` | 选项:`load`, `networkidle`. \ngoto.networkIdleInflight | number | `2` | 允许最大请求数量。只在`goto.waitUntil`: 'networkidle'参数下生效.\ngoto.networkIdleTimeout | number | `2000` | 等待超时时间,只有在 waitUntil: 'networkidle' 下生效.\npdf.scale | number | `1` | 网页渲染比例.\npdf.printBackground | boolean | `false`| 打印背景图形.\npdf.displayHeaderFooter | boolean | `false` | 显示页眉和页脚.\npdf.headerTemplate | string | - | HTML模板，用于作为PDF中每个页面的页眉.\npdf.footerTemplate | string | - | HTML模板，用于作为PDF中每个页面的页脚.\npdf.landscape | boolean | `false` | 页面方向.\npdf.pageRanges | string | - | 可选页面信息，例如“1- 5,7,11 -13”。默认为空字符串，意味着输出所有页面.\npdf.format | string | `A4` | 页面格式,如果设置，则优先于宽度或高度选项.\npdf.width | string | - | 纸张宽度.\npdf.height | string | - | 纸张高度.\npdf.margin.top | string | - | 顶部空白.\npdf.margin.right | string | - | 右边空白.\npdf.margin.bottom | string | - | 底部空白.\npdf.margin.left | string | - | 左侧空白.\nscreenshot.fullPage | boolean | `true` | 如果为真，则获取整个可滚动页面的屏幕截图.\nscreenshot.type | string | `png` | 截图类型,可选值: `png`, `jpeg`\nscreenshot.quality | number | - | JPEG图像的质量，在0-100之间,只适用于当 `screenshot.type` 为 `jpeg`.\nscreenshot.omitBackground | boolean | `false` | 隐藏默认的白色背景，并允许捕获具有透明度的屏幕截图.\nscreenshot.clip.x | number | - | 指定页面裁剪区域左上角的x坐标.\nscreenshot.clip.y | number | - | 指定页面裁剪区域左上角的y坐标.\nscreenshot.clip.width | number | - | 指定页剪切区域的宽度.\nscreenshot.clip.height | number | - | 指定页剪切区域的高度.\n\n## 技术开发\n\n#### Maven\n\n要使用 maven,请将此依赖添加到pom.xml文件中：\n\n```xml\n\n\u003cdependency\u003e\n    \u003cgroupId\u003eorg.aoju\u003c/groupId\u003e\n    \u003cartifactId\u003elancia\u003c/artifactId\u003e\n    \u003cversion\u003e1.2.2\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\n#### Logging\n\n该库使用 [SLF4J](https://www.slf4j.org/) 进行日志记录，并且不附带任何默认日志记录实现。\n\n调试程序将日志级别设置为 TRACE\n\n### 快速开始\n\n#### 1、启动浏览器\n\n```java\n        List\u003cString\u003e argList = new ArrayList\u003c\u003e();\n        Fetcher.on(null);\n        LaunchOption options = new LaunchBuilder().withArgs(argList).withHeadless(false).build();\n        argList.add(\"--no-sandbox\");\n        argList.add(\"--disable-setuid-sandbox\");\n        Puppeteer.launch(options);\n```\n\n在这个例子中，我们明确指明了启动路径，程序就会根据指明的路径启动对应的浏览器，如果没有明确指明路径，那么程序会尝试启动默认安装路径下的 Chrome 浏览器\n\n#### 2、导航至某个页面\n\n```java\n        Fetcher.on(null);\n\n        List\u003cString\u003e argList = new ArrayList\u003c\u003e();\n        LaunchOption options = new LaunchBuilder().withArgs(argList).withHeadless(false).build();\n        argList.add(\"--no-sandbox\");\n        argList.add(\"--disable-setuid-sandbox\");\n        Browser browser = Puppeteer.launch(options);\n        Browser browser2 = Puppeteer.launch(options);\n\n        Page page = browser.newPage();\n        page.goTo(\"http://news.baidu.com/\");\n        browser.close();\n        Page page1 = browser2.newPage();\n        page1.goTo(\"http://news.baidu.com/\");\n```\n\n这个例子中，浏览器导航到具体某个页面后关闭。在这里并没有指明启动路径。argList是放一些额外的命令行启动参数的，在下面资源章节中我会给出相关资料。\n\n#### 3、生成页面的 PDF\n\n```java\n        Fetcher.on(null);\n\n        List\u003cString\u003e argList = new ArrayList\u003c\u003e();\n        LaunchOption options = new LaunchBuilder().withArgs(argList).withHeadless(false).build();\n        argList.add(\"--no-sandbox\");\n        argList.add(\"--disable-setuid-sandbox\");\n        Browser browser = Puppeteer.launch(options);\n        Browser browser2 = Puppeteer.launch(options);\n\n        Page page = browser.newPage();\n        page.goTo(\"http://news.baidu.com/\");\n        PDFOption pdfOptions = new PDFOption();\n        pdfOptions.setPath(\"test.pdf\");\n        page.pdf(pdfOptions);\n        page.close();\n        browser.close();\n```\n\n在这个例子中，导航到某个页面后，将整个页面截图，并写成PDF文件。注意，生成PDF必须在headless模式下才能生效\n\n#### 4、TRACING 性能分析\n\n```java\n        Fetcher.on(null);\n\n        List\u003cString\u003e argList = new ArrayList\u003c\u003e();\n        LaunchOption options = new LaunchBuilder().withArgs(argList).withHeadless(false).build();\n        argList.add(\"--no-sandbox\");\n        argList.add(\"--disable-setuid-sandbox\");\n        Browser browser = Puppeteer.launch(options);\n\n        Page page = browser.newPage();\n        // 开启追踪\n        page.tracing().start(\"/Users/xxx/Desktop/trace.json\");\n        page.goTo(\"http://news.baidu.com/\");\n        page.tracing().stop();\n```\n\n在这个例子中，将在页面导航完成后，生成一个 json 格式的文件，里面包含页面性能的具体数据，可以用 Chrome 浏览器开发者工具打开该 json 文件，并分析性能。\n\n#### 5、页面截图\n\n```java\n        Fetcher.on(null);\n\n        List\u003cString\u003e arrayList = new ArrayList\u003c\u003e();\n        LaunchOption options = new LaunchBuilder().withArgs(arrayList).withHeadless(true).build();\n        arrayList.add(\"--no-sandbox\");\n        arrayList.add(\"--disable-setuid-sandbox\");\n        Browser browser = Puppeteer.launch(options);\n\n        Page page = browser.newPage();\n        page.goTo(\"http://news.baidu.com/\");\n        ScreenshotOption screenshotOptions = new ScreenshotOption();\n        //设置截图范围\n        Clip clip = new Clip(1.0, 1.56, 400, 400);\n        screenshotOptions.setClip(clip);\n        //设置存放的路径\n        screenshotOptions.setPath(\"test.png\");\n        page.screenshot(screenshotOptions);\n```\n\n#### 1. 环境要求\n\n1. 本地运行需要安装 Java 8+及以上版本支持\n2. CentOS(6.x及以下版本未测试) 需要安装如下LIB:\n\n ```\n yum install pango.x86_64 libXcomposite.x86_64 libXcursor.x86_64 libXdamage.x86_64 libXext.x86_64 libXi.x86_64 libXtst.x86_64 cups-libs.x86_64 libXScrnSaver.x86_64 libXrandr.x86_64 GConf2.x86_64 alsa-lib.x86_64 atk.x86_64 gtk3.x86_64 ipa-gothic-fonts xorg-x11-fonts-100dpi xorg-x11-fonts-75dpi xorg-x11-utils xorg-x11-fonts-cyrillic xorg-x11-fonts-Type1 xorg-x11-fonts-misc -y\n ```\n\n如果出现中文，需要安装相关字体\n\n ```\n yum groupinstall \"fonts\" -y\n ```\n\n### 版本提示：\n\n 本项目有java版本和nodejs版本，请切换分支获取不同版本内容\n\n**WARNING:** *至少需要保证2GB左右的内存，一些新闻网站可能会更高甚至需要4GB内存.*\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faoju%2Flancia","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Faoju%2Flancia","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faoju%2Flancia/lists"}