@kne/fastify-puppeteer 1.1.8 → 1.1.10

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.
@@ -278,6 +278,33 @@ module.exports = fp(async (fastify, options) => {
278
278
  }
279
279
  );
280
280
 
281
+ fastify.post(
282
+ `${options.prefix}/parseUrlToPdfBatch`,
283
+ {
284
+ onRequest: options.authenticate,
285
+ schema: {
286
+ description: '接口说明',
287
+ summary: 'url生成pdf文件流',
288
+ body: {
289
+ type: 'object',
290
+ required: ['urlList'],
291
+ properties: {
292
+ options: pdfSchema,
293
+ urlList: { type: 'array', items: { type: 'string' } }
294
+ }
295
+ }
296
+ }
297
+ },
298
+ async (request, reply) => {
299
+ const filename = await services.parseUrlToPdfBatch({
300
+ urlList: request.body.urlList,
301
+ options: request.body.options
302
+ });
303
+ request.body.filename && reply.header('Content-Disposition', `attachment; filename=${encodeURIComponent(request.body.filename)}`);
304
+ return reply.sendFile(filename, { root: options.root });
305
+ }
306
+ );
307
+
281
308
  fastify.get(
282
309
  `${options.prefix}/parseUrlToPdfBatch`,
283
310
  {
@@ -6,10 +6,20 @@ module.exports = async options => {
6
6
  const browser = await puppeteer.launch(options.puppeteerOptions);
7
7
  const deferred = createDeferred(options.maxTaskSize);
8
8
  return {
9
- task: async callback => {
9
+ task: async (callback, pageOptions) => {
10
+ pageOptions = Object.assign(
11
+ {},
12
+ {
13
+ timezone: 'Asia/Shanghai',
14
+ viewport: {}
15
+ },
16
+ pageOptions
17
+ );
10
18
  return await deferred(async () => {
11
19
  const page = await browser.newPage();
12
- await page.setViewport(Object.assign({}, options.pageViewport, { width: options.pageWidth, height: options.pageHeight }));
20
+ console.log('puppeteer task start');
21
+ await page.emulateTimezone(pageOptions.timezone);
22
+ await page.setViewport(Object.assign({}, options.pageViewport, Object.assign({}, { width: options.pageWidth, height: options.pageHeight }, pageOptions.viewport)));
13
23
  const output = await (async () => {
14
24
  try {
15
25
  return {
package/libs/services.js CHANGED
@@ -52,33 +52,33 @@ const pdfSchema = {
52
52
  default: 'A4'
53
53
  },
54
54
  width: {
55
- type: ['string', 'number'],
55
+ oneOf: [{ type: 'number' }, { type: 'string' }],
56
56
  description: "自定义宽度(如 '8.5in', '200px', 200)"
57
57
  },
58
58
  height: {
59
- type: ['string', 'number'],
59
+ oneOf: [{ type: 'number' }, { type: 'string' }],
60
60
  description: "自定义高度(如 '11in', '300px', 300)"
61
61
  },
62
62
  margin: {
63
63
  type: 'object',
64
64
  properties: {
65
65
  top: {
66
- type: ['string', 'number'],
66
+ oneOf: [{ type: 'number' }, { type: 'string' }],
67
67
  description: "上边距(如 '1in', '20px')",
68
68
  default: '0.4in'
69
69
  },
70
70
  right: {
71
- type: ['string', 'number'],
71
+ oneOf: [{ type: 'number' }, { type: 'string' }],
72
72
  description: '右边距',
73
73
  default: '0.4in'
74
74
  },
75
75
  bottom: {
76
- type: ['string', 'number'],
76
+ oneOf: [{ type: 'number' }, { type: 'string' }],
77
77
  description: '下边距',
78
78
  default: '0.4in'
79
79
  },
80
80
  left: {
81
- type: ['string', 'number'],
81
+ oneOf: [{ type: 'number' }, { type: 'string' }],
82
82
  description: '左边距',
83
83
  default: '0.4in'
84
84
  }
@@ -109,6 +109,26 @@ const pdfSchema = {
109
109
  waitForVisible: { type: 'boolean' },
110
110
  waitForSelector: {
111
111
  oneOf: [{ type: 'array', items: { type: 'string' } }, { type: 'string' }]
112
+ },
113
+ timezone: {
114
+ type: 'string',
115
+ description: '时区',
116
+ default: 'Asia/Shanghai'
117
+ },
118
+ viewport: {
119
+ type: 'object',
120
+ properties: {
121
+ width: {
122
+ type: 'number',
123
+ description: '视口宽度',
124
+ default: 1366
125
+ },
126
+ height: {
127
+ type: 'number',
128
+ description: '视口高度',
129
+ default: 768
130
+ }
131
+ }
112
132
  }
113
133
  },
114
134
  additionalProperties: false
@@ -155,7 +175,6 @@ const photoSchema = {
155
175
  description: '裁剪区域高度'
156
176
  }
157
177
  },
158
- required: ['x', 'y', 'width', 'height'],
159
178
  additionalProperties: false
160
179
  },
161
180
  omitBackground: {
@@ -175,6 +194,26 @@ const photoSchema = {
175
194
  waitForVisible: { type: 'boolean' },
176
195
  waitForSelector: {
177
196
  oneOf: [{ type: 'array', items: { type: 'string' } }, { type: 'string' }]
197
+ },
198
+ timezone: {
199
+ type: 'string',
200
+ description: '时区',
201
+ default: 'Asia/Shanghai'
202
+ },
203
+ viewport: {
204
+ type: 'object',
205
+ properties: {
206
+ width: {
207
+ type: 'number',
208
+ description: '视口宽度',
209
+ default: 1366
210
+ },
211
+ height: {
212
+ type: 'number',
213
+ description: '视口高度',
214
+ default: 768
215
+ }
216
+ }
178
217
  }
179
218
  },
180
219
  additionalProperties: false
@@ -219,21 +258,24 @@ module.exports = fp(async (fastify, options) => {
219
258
  };
220
259
 
221
260
  const parseHtmlToPdf = memoCache('parseHtmlToPdf', async ({ html, options }) => {
222
- return await puppeteerPage.task(async ({ page }) => {
223
- await page.setContent(html);
224
- return await page.pdf(
225
- Object.assign(
226
- {},
227
- {
228
- waitUntil: 'networkidle0',
229
- displayHeaderFooter: true,
230
- printBackground: true,
231
- format: 'A4'
232
- },
233
- options
234
- )
235
- );
236
- });
261
+ return await puppeteerPage.task(
262
+ async ({ page }) => {
263
+ await page.setContent(html);
264
+ return await page.pdf(
265
+ Object.assign(
266
+ {},
267
+ {
268
+ waitUntil: 'networkidle0',
269
+ displayHeaderFooter: true,
270
+ printBackground: true,
271
+ format: 'A4'
272
+ },
273
+ options
274
+ )
275
+ );
276
+ },
277
+ { timezone: options?.timezone, viewport: options?.viewport }
278
+ );
237
279
  });
238
280
 
239
281
  const parseHtmlToPdfBatch = memoCache('parseHtmlToPdfBatch', async ({ htmlList, options }) => {
@@ -243,10 +285,13 @@ module.exports = fp(async (fastify, options) => {
243
285
  });
244
286
 
245
287
  const parseHtmlToPhoto = memoCache('parseHtmlToPhoto', async ({ html, options }) => {
246
- return await puppeteerPage.task(async ({ page }) => {
247
- await page.setContent(html);
248
- return await page.screenshot(Object.assign({}, { waitUntil: 'networkidle0', type: 'png' }, options));
249
- });
288
+ return await puppeteerPage.task(
289
+ async ({ page }) => {
290
+ await page.setContent(html);
291
+ return await page.screenshot(Object.assign({}, { waitUntil: 'networkidle0', type: 'png' }, options));
292
+ },
293
+ { timezone: options?.timezone, viewport: options?.viewport }
294
+ );
250
295
  });
251
296
 
252
297
  const parseHtmlToPhotoBatch = memoCache('parseHtmlToPhotoBatch', async ({ htmlList, options }) => {
@@ -256,30 +301,33 @@ module.exports = fp(async (fastify, options) => {
256
301
  });
257
302
 
258
303
  const parseUrlToPdf = memoCache('parseUrlToPdf', async ({ url, options = {} }) => {
259
- return await puppeteerPage.task(async ({ page }) => {
260
- await page.goto(url, {
261
- waitUntil: 'networkidle0'
262
- });
263
- await Promise.all(
264
- (options.waitForSelectors || []).map(waitForSelector => {
265
- return page.waitForSelector(waitForSelector, {
266
- visible: options.waitForVisible || false,
267
- timeout: options.waitForMaxTime || 10000
268
- });
269
- })
270
- );
271
- return await page.pdf(
272
- Object.assign(
273
- {},
274
- {
275
- displayHeaderFooter: true,
276
- printBackground: true,
277
- format: 'A4'
278
- },
279
- options
280
- )
281
- );
282
- });
304
+ return await puppeteerPage.task(
305
+ async ({ page }) => {
306
+ await page.goto(url, {
307
+ waitUntil: 'networkidle0'
308
+ });
309
+ await Promise.all(
310
+ (options.waitForSelectors || []).map(waitForSelector => {
311
+ return page.waitForSelector(waitForSelector, {
312
+ visible: options.waitForVisible || false,
313
+ timeout: options.waitForMaxTime || 10000
314
+ });
315
+ })
316
+ );
317
+ return await page.pdf(
318
+ Object.assign(
319
+ {},
320
+ {
321
+ displayHeaderFooter: true,
322
+ printBackground: true,
323
+ format: 'A4'
324
+ },
325
+ options
326
+ )
327
+ );
328
+ },
329
+ { timezone: options?.timezone, viewport: options?.viewport }
330
+ );
283
331
  });
284
332
 
285
333
  const parseUrlToPdfBatch = memoCache('parseUrlToPdfBatch', async ({ urlList, options }) => {
@@ -289,26 +337,29 @@ module.exports = fp(async (fastify, options) => {
289
337
  });
290
338
 
291
339
  const parseUrlToPhoto = memoCache('parseUrlToPhoto', async ({ url, selector, options = {} }) => {
292
- return await puppeteerPage.task(async ({ page }) => {
293
- await page.goto(url, {
294
- waitUntil: 'networkidle0'
295
- });
296
- await Promise.all(
297
- (options.waitForSelectors || []).map(waitForSelector => {
298
- return page.waitForSelector(waitForSelector, {
299
- visible: options.waitForVisible || false,
300
- timeout: options.waitForMaxTime || 10000
301
- });
302
- })
303
- );
304
- if (selector) {
305
- await page.locator(selector).wait();
306
- const element = await page.$(selector);
307
- const boundingBox = await element.boundingBox();
308
- return await page.screenshot(Object.assign({}, { type: 'png', clip: boundingBox }, options));
309
- }
310
- return await page.screenshot(Object.assign({}, { type: 'png' }, options));
311
- });
340
+ return await puppeteerPage.task(
341
+ async ({ page }) => {
342
+ await page.goto(url, {
343
+ waitUntil: 'networkidle0'
344
+ });
345
+ await Promise.all(
346
+ (options.waitForSelectors || []).map(waitForSelector => {
347
+ return page.waitForSelector(waitForSelector, {
348
+ visible: options.waitForVisible || false,
349
+ timeout: options.waitForMaxTime || 10000
350
+ });
351
+ })
352
+ );
353
+ if (selector) {
354
+ await page.locator(selector).wait();
355
+ const element = await page.$(selector);
356
+ const boundingBox = await element.boundingBox();
357
+ return await page.screenshot(Object.assign({}, { type: 'png' }, options, { clip: boundingBox, fullPage: false }));
358
+ }
359
+ return await page.screenshot(Object.assign({}, { type: 'png' }, options));
360
+ },
361
+ { timezone: options?.timezone, viewport: options?.viewport }
362
+ );
312
363
  });
313
364
 
314
365
  const parseUrlToPhotoBatch = memoCache('parseUrlToPhotoBatch', async ({ urlList, selector, options }) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kne/fastify-puppeteer",
3
- "version": "1.1.8",
3
+ "version": "1.1.10",
4
4
  "description": "用于操作无头浏览器截图保存pdf等",
5
5
  "main": "index.js",
6
6
  "scripts": {