node-pdf2img 0.1.7 → 0.1.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,16 +1,19 @@
1
1
  # node-pdf2img
2
2
 
3
- 高性能 PDF 转图片工具,基于 PDFium 原生渲染器 + Sharp 图像编码。
3
+ 高性能 PDF 转图片工具,支持 PDFium 原生渲染器和 PDF.js 渲染器。
4
4
 
5
5
  [![npm version](https://badge.fury.io/js/node-pdf2img.svg)](https://badge.fury.io/js/node-pdf2img)
6
6
 
7
7
  ## 特性
8
8
 
9
- - **高性能**:使用 PDFium 原生渲染,多线程并行处理
9
+ - **双渲染引擎**:PDFium 原生渲染(高性能)+ PDF.js(纯 JavaScript,无需原生依赖)
10
+ - **高性能**:PDFium 多线程并行处理,整体快 1.7x
11
+ - **流式渲染**:URL 输入支持 HTTP Range 请求,大文件无需完整下载
10
12
  - **多种格式**:支持 WebP、PNG、JPG 输出
11
13
  - **多种输入**:支持本地文件、URL、Buffer
12
14
  - **多种输出**:支持本地文件、Buffer、腾讯云 COS
13
15
  - **CLI + API**:命令行工具和 Node.js 模块双模式
16
+ - **广泛兼容**:支持 GLIBC 2.17+ (CentOS 7/RHEL 7+)
14
17
 
15
18
  ## 安装
16
19
 
@@ -25,14 +28,20 @@ npm install -g node-pdf2img
25
28
  ## 系统要求
26
29
 
27
30
  - Node.js >= 18.0.0
28
- - 支持平台:Linux x64/arm64、macOS x64/arm64、Windows x64
31
+ - 支持平台:
32
+ - Linux x64/arm64 (GLIBC 2.17+,兼容 CentOS 7/RHEL 7+)
33
+ - macOS x64/arm64
34
+ - Windows x64
29
35
 
30
36
  ## CLI 使用
31
37
 
32
38
  ```bash
33
- # 基本用法 - 转换所有页面
39
+ # 基本用法 - 转换所有页面(默认使用 PDFium)
34
40
  pdf2img document.pdf -o ./output
35
41
 
42
+ # 使用 PDF.js 渲染器
43
+ pdf2img document.pdf -o ./output -r pdfjs
44
+
36
45
  # 转换指定页面
37
46
  pdf2img document.pdf -p 1,2,3 -o ./output
38
47
 
@@ -51,6 +60,9 @@ pdf2img document.pdf -f jpg -q 85 -o ./output
51
60
  # 显示 PDF 信息
52
61
  pdf2img document.pdf --info
53
62
 
63
+ # 显示渲染器版本信息
64
+ pdf2img --version-info
65
+
54
66
  # 上传到腾讯云 COS
55
67
  pdf2img document.pdf --cos --cos-prefix images/doc-123
56
68
  ```
@@ -64,8 +76,10 @@ pdf2img document.pdf --cos --cos-prefix images/doc-123
64
76
  | `-w, --width <width>` | 渲染宽度(像素) | `1920` |
65
77
  | `-q, --quality <quality>` | 图片质量(0-100) | `100` |
66
78
  | `-f, --format <format>` | 输出格式:webp, png, jpg | `webp` |
79
+ | `-r, --renderer <renderer>` | 渲染器:pdfium, pdfjs | `pdfium` |
67
80
  | `--prefix <prefix>` | 文件名前缀 | `page` |
68
81
  | `--info` | 仅显示 PDF 信息 | |
82
+ | `--version-info` | 显示渲染器版本信息 | |
69
83
  | `-v, --verbose` | 详细输出 | |
70
84
  | `--cos` | 上传到腾讯云 COS | |
71
85
  | `--cos-prefix <prefix>` | COS key 前缀 | |
@@ -88,7 +102,7 @@ pdf2img document.pdf --cos --cos-prefix images/doc-123
88
102
  ### 基本用法
89
103
 
90
104
  ```javascript
91
- import { convert, getPageCount, isAvailable } from 'node-pdf2img';
105
+ import { convert, getPageCount, isAvailable, RendererType } from 'node-pdf2img';
92
106
 
93
107
  // 检查渲染器是否可用
94
108
  if (!isAvailable()) {
@@ -96,7 +110,7 @@ if (!isAvailable()) {
96
110
  process.exit(1);
97
111
  }
98
112
 
99
- // 转换 PDF 为图片(返回 Buffer)
113
+ // 转换 PDF 为图片(返回 Buffer,默认使用 PDFium
100
114
  const result = await convert('./document.pdf');
101
115
  console.log(`转换了 ${result.renderedPages} 页`);
102
116
 
@@ -106,6 +120,24 @@ for (const page of result.pages) {
106
120
  }
107
121
  ```
108
122
 
123
+ ### 使用 PDF.js 渲染器
124
+
125
+ ```javascript
126
+ import { convert, RendererType, isPdfjsAvailable } from 'node-pdf2img';
127
+
128
+ // 检查 PDF.js 渲染器是否可用
129
+ if (isPdfjsAvailable()) {
130
+ const result = await convert('./document.pdf', {
131
+ renderer: RendererType.PDFJS, // 或直接使用 'pdfjs'
132
+ });
133
+ console.log(`使用 PDF.js 转换了 ${result.renderedPages} 页`);
134
+ }
135
+ ```
136
+
137
+ > **渲染器选择建议**:
138
+ > - **PDFium**(默认):高性能,适合大多数场景,整体快 1.7x
139
+ > - **PDF.js**:纯 JavaScript,无需原生依赖,适合超大文件(>50MB)或无法使用原生模块的环境
140
+
109
141
  ### 保存到文件
110
142
 
111
143
  ```javascript
@@ -200,8 +232,15 @@ const result = await convert('https://example.com/document.pdf', {
200
232
  outputType: 'file',
201
233
  outputDir: './output',
202
234
  });
235
+
236
+ // 查看流式渲染统计(仅 URL 输入时存在)
237
+ if (result.streamStats) {
238
+ console.log(`流式渲染: 缓存命中 ${result.streamStats.cacheHits} 次`);
239
+ }
203
240
  ```
204
241
 
242
+ > **流式渲染**:对于大于 2MB 的远程 PDF,会自动使用 HTTP Range 请求按需获取数据,避免完整下载。小于 2MB 的文件会直接下载后渲染,减少 Range 请求开销。
243
+
205
244
  ### 上传到腾讯云 COS
206
245
 
207
246
  ```javascript
@@ -256,6 +295,7 @@ PDF 转图片。
256
295
  - `prefix` (string):文件名前缀,默认 'page'
257
296
  - `format` ('webp' | 'png' | 'jpg'):输出格式,默认 'webp'
258
297
  - `targetWidth` (number):渲染宽度,默认 1280
298
+ - `renderer` ('pdfium' | 'pdfjs'):渲染器,默认 'pdfium'
259
299
  - `webp` (object):WebP 编码选项
260
300
  - `quality` (number):质量 0-100,默认 80
261
301
  - `jpeg` (object):JPEG 编码选项
@@ -276,15 +316,30 @@ PDF 转图片。
276
316
 
277
317
  **返回:** Promise\<number\>
278
318
 
279
- ### `isAvailable()`
319
+ ### `isAvailable(renderer?)`
320
+
321
+ 检查渲染器是否可用。
322
+
323
+ **参数:**
324
+ - `renderer` ('pdfium' | 'pdfjs'):可选,指定检查的渲染器,默认检查 PDFium
325
+
326
+ **返回:** boolean
327
+
328
+ ### `isPdfjsAvailable()`
280
329
 
281
- 检查原生渲染器是否可用。
330
+ 检查 PDF.js 渲染器是否可用。
282
331
 
283
332
  **返回:** boolean
284
333
 
285
334
  ### `getVersion()`
286
335
 
287
- 获取原生渲染器版本信息。
336
+ 获取 PDFium 渲染器版本信息。
337
+
338
+ **返回:** string
339
+
340
+ ### `getPdfjsVersion()`
341
+
342
+ 获取 PDF.js 渲染器版本信息。
288
343
 
289
344
  **返回:** string
290
345
 
@@ -299,8 +354,39 @@ PDF 转图片。
299
354
  | 变量 | 说明 | 默认值 |
300
355
  |------|------|--------|
301
356
  | `PDF2IMG_THREAD_COUNT` | 工作线程数 | CPU 核心数 |
357
+ | `PDF2IMG_RENDERER` | 默认渲染器 (pdfium/pdfjs) | `pdfium` |
302
358
  | `PDF2IMG_DEBUG` | 启用调试日志 | `false` |
303
359
 
360
+ ## 渲染器对比
361
+
362
+ | 特性 | PDFium | PDF.js |
363
+ |------|--------|--------|
364
+ | 性能 | ⚡ 快 1.7x | 普通 |
365
+ | 依赖 | 原生模块 | 纯 JavaScript |
366
+ | 大文件 (>50MB) | 普通 | ⚡ 更快 |
367
+ | 兼容性 | Linux/macOS/Windows | 所有平台 |
368
+ | 流式渲染 | ✓ | ✓ |
369
+
370
+ ## 架构
371
+
372
+ 模块化设计,职责分离:
373
+
374
+ ```
375
+ src/
376
+ ├── core/
377
+ │ ├── converter.js # 主 API 入口
378
+ │ ├── renderer.js # PDF 渲染逻辑(流式/下载/本地)
379
+ │ ├── thread-pool.js # 线程池管理
380
+ │ ├── downloader.js # 远程文件下载
381
+ │ ├── output-handler.js # 文件保存和 COS 上传
382
+ │ └── config.js # 配置常量
383
+ ├── renderers/
384
+ │ ├── native.js # PDFium 原生渲染器
385
+ │ └── pdfjs.js # PDF.js 渲染器(分片加载)
386
+ └── utils/
387
+ └── logger.js # 日志工具
388
+ ```
389
+
304
390
  ## 许可证
305
391
 
306
392
  MIT
package/bin/cli.js CHANGED
@@ -12,8 +12,13 @@
12
12
  * pdf2img document.pdf -p 1,2,3 -o ./output
13
13
  * pdf2img document.pdf --quality 90 --width 1920 -o ./output
14
14
  * pdf2img document.pdf --format png -o ./output # 输出 PNG 格式
15
+ * pdf2img document.pdf --renderer pdfjs -o ./output # 使用 PDF.js 渲染器
15
16
  * pdf2img document.pdf --cos --cos-prefix images/doc # 上传到 COS
16
17
  *
18
+ * 渲染器:
19
+ * pdfium - PDFium 原生渲染器(默认,高性能)
20
+ * pdfjs - PDF.js 渲染器(纯 JavaScript,无需原生依赖)
21
+ *
17
22
  * COS 环境变量:
18
23
  * COS_SECRET_ID - 腾讯云 SecretId
19
24
  * COS_SECRET_KEY - 腾讯云 SecretKey
@@ -42,10 +47,10 @@ try {
42
47
 
43
48
  // 处理 --version-info 选项(在解析前检查)
44
49
  if (process.argv.includes('--version-info')) {
45
- const { isAvailable, getVersion } = await import('../src/index.js');
50
+ const { isAvailable, getVersion, RendererType } = await import('../src/index.js');
46
51
  console.log(`pdf2img v${pkg.version}`);
47
- console.log(`原生渲染器: ${getVersion()}`);
48
- console.log(`可用: ${isAvailable() ? '' : ''}`);
52
+ console.log(`PDFium 渲染器: ${isAvailable(RendererType.PDFIUM) ? getVersion(RendererType.PDFIUM) : '不可用'}`);
53
+ console.log(`PDF.js 渲染器: ${isAvailable(RendererType.PDFJS) ? '可用' : '不可用'}`);
49
54
  process.exit(0);
50
55
  }
51
56
 
@@ -59,6 +64,7 @@ program
59
64
  .option('-w, --width <width>', '目标渲染宽度(像素)', '1920')
60
65
  .option('-q, --quality <quality>', '图片质量(0-100,用于 webp/jpg)', '100')
61
66
  .option('-f, --format <format>', '输出格式:webp, png, jpg', 'webp')
67
+ .option('-r, --renderer <renderer>', '渲染器:pdfium(默认)或 pdfjs', 'pdfium')
62
68
  .option('--prefix <prefix>', '输出文件名前缀', 'page')
63
69
  .option('--info', '仅显示 PDF 信息(页数)')
64
70
  .option('--version-info', '显示原生渲染器版本')
@@ -77,20 +83,31 @@ program
77
83
  }
78
84
 
79
85
  // 动态导入主模块
80
- const { convert, getPageCount, isAvailable, getVersion } = await import('../src/index.js');
86
+ const { convert, getPageCount, isAvailable, getVersion, RendererType } = await import('../src/index.js');
81
87
 
82
88
  // 显示版本信息
83
89
  if (options.versionInfo) {
84
90
  console.log(`pdf2img v${pkg.version}`);
85
- console.log(`原生渲染器: ${getVersion()}`);
86
- console.log(`可用: ${isAvailable() ? '' : ''}`);
91
+ console.log(`PDFium 渲染器: ${isAvailable(RendererType.PDFIUM) ? getVersion(RendererType.PDFIUM) : '不可用'}`);
92
+ console.log(`PDF.js 渲染器: ${isAvailable(RendererType.PDFJS) ? '可用' : '不可用'}`);
87
93
  return;
88
94
  }
89
95
 
90
- // 检查 native renderer
91
- if (!isAvailable()) {
92
- console.error('错误:原生渲染器不可用。');
93
- console.error('请确保 PDFium 库已正确安装。');
96
+ // 验证渲染器
97
+ const renderer = options.renderer.toLowerCase();
98
+ if (renderer !== 'pdfium' && renderer !== 'pdfjs') {
99
+ console.error(`错误:不支持的渲染器 "${options.renderer}"。支持的渲染器:pdfium, pdfjs`);
100
+ process.exit(1);
101
+ }
102
+
103
+ // 检查渲染器可用性
104
+ if (!isAvailable(renderer)) {
105
+ if (renderer === 'pdfium') {
106
+ console.error('错误:PDFium 原生渲染器不可用。');
107
+ console.error('请确保 PDFium 库已正确安装,或使用 --renderer pdfjs 切换到 PDF.js 渲染器。');
108
+ } else {
109
+ console.error('错误:PDF.js 渲染器不可用。');
110
+ }
94
111
  process.exit(1);
95
112
  }
96
113
 
@@ -111,17 +128,15 @@ program
111
128
 
112
129
  // 仅显示 PDF 信息
113
130
  if (options.info) {
114
- if (isUrl) {
115
- console.error('错误:--info 选项仅支持本地文件');
116
- process.exit(1);
117
- }
118
-
119
131
  try {
120
- const pageCount = getPageCount(input);
121
- const stat = fs.statSync(input);
122
- console.log(`文件: ${path.basename(input)}`);
123
- console.log(`大小: ${(stat.size / 1024 / 1024).toFixed(2)} MB`);
132
+ const pageCount = await getPageCount(input, { renderer });
133
+ if (!isUrl) {
134
+ const stat = fs.statSync(input);
135
+ console.log(`文件: ${path.basename(input)}`);
136
+ console.log(`大小: ${(stat.size / 1024 / 1024).toFixed(2)} MB`);
137
+ }
124
138
  console.log(`页数: ${pageCount}`);
139
+ console.log(`渲染器: ${renderer}`);
125
140
  } catch (err) {
126
141
  console.error(`错误: ${err.message}`);
127
142
  process.exit(1);
@@ -143,6 +158,7 @@ program
143
158
  targetWidth: parseInt(options.width, 10),
144
159
  quality: parseInt(options.quality, 10),
145
160
  format: format,
161
+ renderer: renderer,
146
162
  };
147
163
 
148
164
  // COS 模式
@@ -195,7 +211,7 @@ program
195
211
 
196
212
  const duration = Date.now() - startTime;
197
213
 
198
- spinner.succeed(`${modeText}完成 ${result.renderedPages}/${result.numPages} 页,格式: ${result.format.toUpperCase()},耗时 ${duration}ms`);
214
+ spinner.succeed(`${modeText}完成 ${result.renderedPages}/${result.numPages} 页,格式: ${result.format.toUpperCase()},渲染器: ${result.renderer},耗时 ${duration}ms`);
199
215
 
200
216
  // 显示结果
201
217
  if (options.cos) {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "node-pdf2img",
3
- "version": "0.1.7",
4
- "description": "High-performance PDF to image converter using PDFium native renderer",
3
+ "version": "0.1.9",
4
+ "description": "High-performance PDF to image converter using PDFium native renderer or PDF.js",
5
5
  "type": "module",
6
6
  "main": "./src/index.js",
7
7
  "types": "./src/index.d.ts",
@@ -29,6 +29,7 @@
29
29
  "image",
30
30
  "converter",
31
31
  "pdfium",
32
+ "pdfjs",
32
33
  "webp",
33
34
  "native",
34
35
  "cli"
@@ -53,9 +54,13 @@
53
54
  "dotenv": "^16.0.3",
54
55
  "ora": "^8.0.0",
55
56
  "p-limit": "^7.2.0",
57
+ "pdfjs-dist": "^4.0.0",
56
58
  "piscina": "^5.1.4",
57
59
  "sharp": "^0.33.0",
58
- "node-pdf2img-native": "^1.1.8"
60
+ "node-pdf2img-native": "^1.1.10"
61
+ },
62
+ "optionalDependencies": {
63
+ "canvas": "^2.11.0"
59
64
  },
60
65
  "devDependencies": {
61
66
  "@types/node": "^20.0.0"
@@ -2,6 +2,15 @@
2
2
  * PDF2IMG 配置
3
3
  */
4
4
 
5
+ // ==================== 渲染器类型 ====================
6
+ export const RendererType = {
7
+ PDFIUM: 'pdfium', // PDFium 原生渲染器(默认,高性能)
8
+ PDFJS: 'pdfjs', // PDF.js 渲染器(纯 JavaScript,无需原生依赖)
9
+ };
10
+
11
+ // 默认渲染器
12
+ export const DEFAULT_RENDERER = process.env.PDF2IMG_RENDERER || RendererType.PDFIUM;
13
+
5
14
  // ==================== 渲染配置 ====================
6
15
  export const RENDER_CONFIG = {
7
16
  // 目标渲染宽度(像素)