生成多页PDF时Node.js路由冲突及解决方案

生成多页pdf时node.js路由冲突及解决方案

摘要:本文档旨在解决在使用Node.js和Puppeteer生成多页PDF时遇到的路由冲突问题。我们将分析导致 “invalid input syntax for type bigint” 错误的根本原因,并提供修改路由以避免冲突的有效方法,确保程序能够正确处理 “all” 参数,生成包含所有ID的PDF文件。

在构建Node.js应用程序,特别是涉及动态路由和数据库交互时,路由冲突是一个常见的问题。当多个路由模式可以匹配同一个URL时,服务器可能会选择错误的路由处理请求,导致意外的错误。本教程将探讨如何避免在使用Express.js和Puppeteer生成PDF文件时遇到的这类问题。

问题分析

错误信息 “error: invalid input syntax for type bigint: “all”” 表明数据库查询期望一个数字类型的ID,但实际接收到了字符串 “all”。这通常发生在路由参数被错误地传递给数据库查询时。

在提供的代码中,问题出在以下路由定义:

router.get('/:database/:tipo/:ids/:limite?.pdf', async (req, res) => { ... });

当请求的URL为 /:database/:type/all.pdf 时,Express.js的路由匹配机制可能会将其解析为以下参数:

database: 数据库名称tipo: 类型ids: “all”limite: undefined

然而,由于存在另一个路由 router.get(‘/:database/:tipo/:id.pdf’) 用于生成单个PDF,当请求 /:database/:tipo/all.pdf 时,Express.js可能会将 all 错误地解析为 :id 参数,导致后续的数据库查询出错。

解决方案:修改路由

避免路由冲突最直接的方法是修改其中一个路由的定义,使其不再与另一个路由发生重叠。根据提供的解决方案,将生成多个PDF的路由的 .pdf 后缀更改为 .pdfs 可以有效解决问题。

修改后的路由定义如下:

router.get('/:database/:tipo/:ids/:limite?.pdfs', async (req, res) => { ... });

现在,请求 /:database/:tipo/all.pdfs 将明确匹配到新的路由,而不会与生成单个PDF的路由发生冲突。

代码示例(修改后的路由)

以下是修改后的代码示例,重点在于路由的更改:

router.get('/:database/:tipo/:ids/:limite?.pdfs', async (req, res) => {  const { database, tipo, ids, limite } = req.params;  let idsArray;  if (ids === "all") {    const pool = new Pool({      user: process.env.POSTGRES_USER,      host: process.env.POSTGRES_HOST,      database: database,      password: process.env.POSTGRES_PASSWORD,      port: process.env.POSTGRES_PORT,    });    let query = `SELECT DISTINCT id FROM controle_interno.${tipo} ORDER BY id ASC`;    if (limite) {      query += ` LIMIT ${limite}`;    }    const result = await pool.query(query);    idsArray = result.rows.map(row => row.id);  } else {    idsArray = ids.split(",");  }  const pdfs = [];  const browser = await puppeteer.launch();  const page = await browser.newPage();  for (let i = 0; i  {      const button = document.getElementById('gerar-pdf');      button.remove();    });  const pdfBytes = await page.pdf({ format: 'A4', printBackground: true, pageRanges: '1' });  pdfs.push(await PDFDocument.load(pdfBytes));} catch (err) {  console.error(err.stack); }}  await browser.close();  const mergedPdf = await PDFDocument.create();  for (const pdf of pdfs) {    const copiedPages = await mergedPdf.copyPages(pdf, pdf.getPageIndices());    copiedPages.forEach((page) => mergedPdf.addPage(page));  }  const pdfBytes = await mergedPdf.save();  const filePath = path.join(__dirname, 'relatorio.pdf');  await fs.promises.mkdir(path.dirname(filePath), { recursive: true });  await fs.promises.writeFile(filePath, pdfBytes);  res.set({    'Content-Type': 'application/pdf',    'Content-Disposition': 'attachment; filename=relatorio.pdf',    'Content-Length': pdfBytes.length  });  const stream = fs.createReadStream(filePath);  stream.pipe(res);  res.on('finish', async () => {        // apaga o arquivo do diretório        await fs.promises.unlink(filePath)});  });

注意事项:

确保所有客户端代码(例如前端JavaScript)也更新为使用新的路由URL(例如,将 all.pdf 更改为 all.pdfs)。在部署更改之前,彻底测试所有相关的路由,以确保没有引入新的问题。

总结

路由冲突是Node.js开发中需要注意的问题。通过仔细设计路由模式,并避免重叠或模糊的定义,可以有效地防止这类问题的发生。在本例中,通过简单地修改路由后缀,成功解决了 “invalid input syntax for type bigint” 错误,并确保了应用程序能够正确处理生成多个PDF的请求。在实际开发中,应该始终优先考虑路由的清晰性和可维护性,以提高应用程序的健壮性。

以上就是生成多页PDF时Node.js路由冲突及解决方案的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1512910.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2025年12月20日 07:24:29
下一篇 2025年12月20日 07:24:38

相关推荐

  • React-Redux应用中联系人更新功能的实现与常见错误解析

    本文深入探讨了在react-redux应用中实现数据更新功能的正确方法,特别针对联系人管理场景。通过分析一个常见的payload不匹配错误,文章详细阐述了如何同步修改action creator、reducer和组件中的dispatch逻辑,确保数据能够正确地被识别和更新。教程提供了修正后的代码示例…

    2025年12月21日
    000
  • 使用Google Apps Script将Google文档导出为PDF并实现下载

    本文详细介绍了如何利用Google Apps Script将Google文档程序化地转换为PDF格式,并提供下载链接。通过结合`DriveApp`服务和客户端脚本,用户可以从Google表格触发操作,自动生成文档内容,将其导出为PDF文件,并直接下载,实现高效的自动化工作流程。 在日常工作中,我们经…

    2025年12月21日
    000
  • JavaScript中的性能分析工具使用指南_javascript性能优化

    掌握Chrome DevTools的Performance面板可定位JS性能瓶颈,使用console.time()计时代码块,Memory面板检测内存泄漏,User Timing API标记关键阶段,定期分析以优化网页性能。 JavaScript性能分析是优化网页和应用的关键步骤。通过使用现代浏览器…

    2025年12月21日
    000
  • Svelte中数据导入的最佳实践:区分组件与纯数据模块

    在svelte开发中,初学者常遇到的一个误区是将svelte组件文件(`.svelte`)误用于导出纯数据,导致意外地导入了组件实例而非数据本身。本文将详细解析这一问题,阐明svelte组件与普通javascript模块的导入机制差异,并提供正确导入数据的最佳实践,确保开发者能够高效、清晰地管理项目…

    2025年12月21日
    000
  • Redux状态持久化:浏览器中Reducer状态的存储与恢复教程

    在redux应用中,为提升用户体验,管理ui配置等关键状态在页面重载后保持不变至关重要。本教程将深入探讨两种主要的redux reducer状态持久化策略:通过浏览器localstorage手动实现状态的加载与保存,以及利用如redux-persist等第三方库简化这一过程,帮助开发者构建更健壮的应…

    2025年12月21日
    000
  • Snowflake JavaScript 存储过程:获取指定日期的下一个周六

    本教程详细介绍了如何在 snowflake 中使用 javascript 存储过程,根据表中最大日期字段计算并获取下一个周六的日期。文章将演示正确的存储过程实现方式,并解决在将 sql 查询集成到 javascript 代码时可能遇到的常见语法错误,确保日期计算功能稳定运行。 引言:在Snowfla…

    2025年12月21日
    000
  • 使用JavaScript实现颜色主题切换_javascript实战

    答案:通过JavaScript控制CSS类切换实现主题变换。首先添加切换按钮并设置默认主题类,接着用CSS自定义属性定义亮暗色变量并应用到body,再通过JavaScript监听按钮点击事件切换dark-theme类,同时利用localStorage保存和读取用户偏好,确保刷新后主题保持,最后可扩展…

    2025年12月21日
    000
  • JavaScript实现无限滚动加载功能_javascript交互

    答案是使用JavaScript监听滚动事件并结合防抖机制实现无限加载。通过判断window.innerHeight + window.scrollY是否接近document.body.offsetHeight来触发数据加载,利用setTimeout防抖避免频繁请求,同时设置isLoading状态防止…

    2025年12月21日
    000
  • JavaScript中的模块联邦(Module Federation)初探_javascript微前端

    模块联邦是Webpack 5实现微前端的核心技术,允许运行时动态共享模块。通过配置exposes和remotes,子应用可独立开发部署,并按需加载远程组件,如UserProfile;支持技术栈隔离与公共依赖共享(如React),提升构建效率与系统可维护性。典型应用于大型系统拆分、多团队协作及渐进式迁…

    2025年12月21日
    000
  • 使用Clipboard API实现前端剪贴板操作_javascript技巧

    现代浏览器支持Clipboard API,可安全异步读写剪贴板。1. 检测navigator.clipboard是否存在以判断兼容性;2. 用writeText()写入文本;3. 用readText()读取文本,需用户触发;4. 受同源与权限限制,仅HTTPS或localhost可用,需用户手势激活…

    2025年12月21日
    000
  • 使用JavaScript实现一个简单的无限滚动_javascript性能优化

    使用虚拟列表只渲染可见区域,结合节流控制滚动事件频率,并通过DocumentFragment和transform减少重排重绘,实现高性能无限滚动。 实现无限滚动时,如果不做性能优化,很容易导致页面卡顿、内存占用过高。关键在于减少DOM元素数量、合理使用事件监听和避免频繁重排重绘。以下是几个核心思路与…

    2025年12月21日
    000
  • 优化Fetch异步链式调用与React状态管理:避免常见陷阱

    本文深入探讨了在javascript中处理fetch异步请求链和react状态更新时常见的陷阱。主要解决了在`promise.then()`链中未返回promise导致后续操作过早执行的问题,并强调了react `usestate`更新的异步性。通过对比`.then()`和`async/await`…

    2025年12月21日
    000
  • 使用纯CSS实现固定头部、动态底部与可滚动叠加层

    本文详细介绍了如何利用CSS实现一个复杂的布局需求:在固定头部和动态高度的底部之间,创建一个可滚动且不溢出的叠加层。通过巧妙运用Flexbox布局、绝对定位以及CSS `calc()` 函数结合视口单位(`vh`)和百分比单位,解决了叠加层动态定位和高度计算的挑战,确保其始终位于指定区域内并支持内容…

    2025年12月21日 好文分享
    000
  • JavaScript事件循环机制完全解析_javascript技巧

    事件循环机制解释了JavaScript异步行为的执行顺序。JavaScript采用单线程模型,通过事件循环实现非阻性I/O:当遇到异步操作如setTimeout或Promise时,JS引擎将其交给浏览器模块处理,完成后将回调加入任务队列。事件循环不断从队列中取出任务执行,分为宏任务和微任务两类。宏任…

    2025年12月21日
    000
  • jquery中向上遍DOM树的方法有哪些?

    向上遍历DOM树的方法包括:1. parent()获取直接父元素;2. parents()获取所有祖先元素;3. closest()查找最近的匹配祖先;4. parentsUntil()获取指定范围内的祖先元素。 在 jQuery 中,向上遍历 DOM 树的方法主要用于查找某个元素的父级或祖先元素。…

    2025年12月21日
    000
  • 使用JavaScript实现一个简单的倒计时组件_javascript UI组件

    答案:该倒计时组件通过JavaScript实现每秒更新显示,归零后触发回调。使用方法为调用createCountdown函数传入元素ID、初始秒数和结束回调,支持重置与样式扩展,结构清晰且轻量实用。 实现一个简单的倒计时组件,关键在于定时更新显示时间,并在倒计时结束后触发回调。下面是一个基于原生 J…

    2025年12月21日
    000
  • 解决fetch在then()中首次点击不工作的问题

    本文针对在使用`fetch` API进行POST请求后,紧接着在`.then()`回调中执行GET请求时,第一次点击事件无法正确获取数据的问题,提供了详细的分析和解决方案。通过结合`async/await`和理解React状态更新的异步性,可以有效避免此类问题,并确保数据操作的准确性和可靠性。 在使…

    2025年12月21日
    000
  • JavaScript 对象创建:对象字面量与 new Object() 的比较

    对象字面量语法更简洁、可读性更强,性能更优,是创建对象的首选方式;2. new Object() 虽功能等价但冗长且性能略低,仅在特殊动态场景使用。 在 JavaScript 中,创建对象是日常开发中的基础操作。两种常见方式是使用对象字面量和内置构造函数new Object()。虽然它们都能生成对象…

    2025年12月21日
    000
  • 使用JavaScript操作DOM的性能优化技巧_javascript性能优化

    减少DOM访问、批量操作使用DocumentFragment、避免强制同步布局、采用事件委托。通过缓存查询结果、合并DOM更新、分离读写操作及绑定父级监听,可显著提升JavaScript性能,降低重排重绘开销,使页面响应更流畅。 在使用JavaScript操作DOM时,性能问题常常成为影响页面响应速…

    2025年12月21日
    000
  • 解决fetch在then()中首次点击无响应的问题

    本文旨在解决在使用`fetch` API时,在`.then()`回调中进行异步操作,首次点击事件无响应的问题。通过分析原因,提供使用`return`关键字确保Promise链正确执行,并推荐使用`async/await`语法简化代码,提高可读性和可维护性。同时,针对React环境,讨论了`useSt…

    2025年12月21日
    000

发表回复

登录后才能评论
关注微信