前端使用pdf-lib库实现pdf合并,window.open预览合并后的pdf
最近出差开了好多发票,写了一个pdf合并网站,用于把多张发票pdf合并成一张,方便打印
使用pdf-lib这个库实现的pdf合并功能,预览使用的是浏览器自身查看pdf功能
源码
网页地址 https://zqy233.github.io/PDF-merge/
<!DOCTYPE html>
<html><head><title>PDF合并</title><script src="https://cdn.jsdelivr.net/npm/pdf-lib@1.17.1/dist/pdf-lib.min.js"></script></head><body><input type="file" id="fileInput" multiple /><button onclick="previewMergePDF()">预览合并的PDF</button><button onclick="downloadMergePDF()">下载合并的PDF</button><script>async function previewMergePDF() {const fileInput = document.getElementById("fileInput");const files = fileInput.files;if (files.length < 2) {alert("请至少选择两个PDF文件进行合并!");return;}// 创建一个新的PDF文档const mergedPdf = await PDFLib.PDFDocument.create();// 遍历选择的每个文件for (let i = 0; i < files.length; i++) {const file = files[i];const reader = new FileReader();// 读取文件内容const fileContents = await new Promise((resolve, reject) => {reader.onload = function (event) {resolve(event.target.result);};reader.onerror = function (event) {reject(new Error("文件读取错误。"));};reader.readAsArrayBuffer(file);});// 将PDF文件添加到合并的PDF文档中const pdf = await PDFLib.PDFDocument.load(fileContents);const copiedPages = await mergedPdf.copyPages(pdf,pdf.getPageIndices());copiedPages.forEach((page) => {mergedPdf.addPage(page);});}// 使用浏览器自带预览功能,预览合并后的PDFconst mergedPdfBytes = await mergedPdf.save();const mergedPdfBlob = new Blob([mergedPdfBytes], {type: "application/pdf",});const fileURL = URL.createObjectURL(mergedPdfBlob);window.open(fileURL);}async function downloadMergePDF() {const fileInput = document.getElementById("fileInput");const files = fileInput.files;if (files.length < 2) {alert("请至少选择两个PDF文件进行合并!");return;}const mergedPdf = await PDFLib.PDFDocument.create();for (let i = 0; i < files.length; i++) {const file = files[i];const reader = new FileReader();const fileContents = await new Promise((resolve, reject) => {reader.onload = function (event) {resolve(event.target.result);};reader.onerror = function (event) {reject(new Error("文件读取错误。"));};reader.readAsArrayBuffer(file);});const pdf = await PDFLib.PDFDocument.load(fileContents);const copiedPages = await mergedPdf.copyPages(pdf,pdf.getPageIndices());copiedPages.forEach((page) => {mergedPdf.addPage(page);});}const mergedPdfFile = await mergedPdf.saveAsBase64();const downloadLink = document.createElement("a");downloadLink.href = "data:application/pdf;base64," + mergedPdfFile;downloadLink.download = "merged.pdf";downloadLink.click();}</script></body>
</html>相关文章:
前端使用pdf-lib库实现pdf合并,window.open预览合并后的pdf
最近出差开了好多发票,写了一个pdf合并网站,用于把多张发票pdf合并成一张,方便打印 使用pdf-lib这个库实现的pdf合并功能,预览使用的是浏览器自身查看pdf功能 源码 网页地址 https://zqy233.github.io/PDF-merge/ <!DOCTYPE h…...
计算机网络相关知识点总结(二)
比特bit是计算机中数据量的最小单位,可简记为b。字节Byte也是计算机中数据量的单位,可简记为B,1B8bit。常用的数据量单位还有kB、MB、GB、TB等,其中k、M、G、T的数值分别为 2 10 2^{10} 210, 2 20 2^{20} 220, 2 30 2^{30} 230, 2 40 2^{40} 240。 K, M, G, T 分别对应以下…...
Redmine与Gitlab整合(实战版)
网上查了很多文章,总结一下。 安装过程略。可参考:(84条消息) Redmine与Gitlab功能集成_redmine gitlab_羽之大公公的博客-CSDN博客 配置集成的方法,参考: Redmine与GitLab集成 (ngui.cc) 修改ssh-key密码的方法,参…...
(3)深度学习学习笔记-简单线性模型
文章目录 一、线性模型二、实例1.pytorch求导功能2.简单线性模型(人工数据集) 来源 一、线性模型 一个简单模型:假设一个房子的价格由卧室、卫生间、居住面积决定,用x1,x2,x3表示。 那么房价y就可以认为yw…...
pytorch3d 安装报错 RuntimeError: Not compiled with GPU support pytorch3d
安装环境 NVIDIA GeForce RTX 3090 cuda 11.3 python 3.8.5 torch 1.11.0 torchvision 0.12.0 环境安装命令 conda install pytorch1.11.0 torchvision0.12.0 torchaudio0.11.0 cudatoolkit11.3 -c pytorch安装pytorch3d参考官网链接 https://github.com/facebookresearch/p…...
spring工程的启动流程?bean的生命周期?提供哪些扩展点?管理事务?解决循环依赖问题的?事务传播行为有哪些?
1.Spring工程的启动流程: Spring工程的启动流程主要包括以下几个步骤: 加载配置文件:Spring会读取配置文件(如XML配置文件或注解配置)来获取应用程序的配置信息。实例化并初始化IoC容器:Spring会创建并初…...
使用 Zabbix 监控 RocketMQ列举监控项和触发器
在使用 Zabbix 监控 RocketMQ 的过程中,以下是一些可能的监控项和触发器: 监控项 集群总体健康状况生产者和消费者的连接数量Broker 的状态消息的生产和消费速度队列深度(即队列中的消息数量)磁盘空间使用内存使用CPU使用网络流…...
uniApp:路由与页面跳转及传参
方式一:声明式导航 声明式导航,通过组件进行跳转。官方文档:详情 使用 navigator 组件进行页面跳转。 属性类型默认值说明urlString应用内的跳转链接,值为相对路径或绝对路径,如:“…/first/first”&#x…...
Java中操作文件(二)
目录 一、什么是数据流 二、InputStream概述 2.1、方法 2.2、说明 三、FileInputStream概述 3.1、构造方法 3.2、利用Scanner进行字符串读取,简化操作 四、OutputStream概述 4.1、方法 4.2、PrinterWriter简化写操作 五、小程序练习 示例1 示例…...
springboot+vue在线考试系统(java项目源码+文档)
风定落花生,歌声逐流水,大家好我是风歌,混迹在java圈的辛苦码农。今天要和大家聊的是一款基于springboot的在线考试系统。项目源码以及部署相关请联系风歌,文末附上联系信息 。 💕💕作者:风歌&a…...
样式方案:在 Vite 中接入现代化的 CSS 工程化方案
上一小节,我们使用 Vite 初始化了一个 Web 项目,迈出了使用 Vite 的第一步。但在实际工作中,仅用 Vite 官方的脚手架项目是不够的,往往还需要考虑诸多的工程化因素,借助 Vite 本身的配置以及业界的各种生态,…...
C#获取根目录实现方法汇总
以下是C#获取不同类型项目根目录的实现方法汇总,以及在 .NET Core 中获取项目根目录的方法: 控制台应用程序 string rootPath Environment.CurrentDirectory; string rootPath AppDomain.CurrentDomain.BaseDirectory; string rootPath Path.GetFul…...
vue获取当前坐标并通过天地图逆转码为省市区
因为需求需要获取用户当前的地理位置用于分析 通过原生的navigator.geolocation.getCurrentPosition获取经纬度 这个方法在谷歌浏览器会失效(原因未知),目前ie浏览器是可以获取的 getCurrentPosition() {if (navigator.geolocation) {var o…...
【MySQL】事务及其隔离性/隔离级别
目录 一、事务的概念 1、事务的四种特性 2、事务的作用 3、存储引擎对事务的支持 4、事务的提交方式 二、事务的启动、回滚与提交 1、准备工作:调整MySQL的默认隔离级别为最低/创建测试表 2、事务的启动、回滚与提交 3、启动事务后未commit,但是…...
计算机由于找不到d3dx9_35.dll,无法启动软件游戏的三个修复方法
在打开游戏的时候,计算机提示由于找不到d3dx9_35.dll,无法正常启动运行。这个是为什么呢?d3dx9_35.dll是DirectX 9.0里面的一个动态连结库文件,它包含了Direct3D、DirectPlay几个组件的二进制文件,为软件提供了多媒体图…...
第三章 模型篇:模型与模型的搭建
写在前面的话 这部分只解释代码,不对线性层(全连接层),卷积层等layer的原理进行解释。 尽量写的比较全了,但是自身水平有限,不太确定是否有遗漏重要的部分。 教程参考: https://pytorch.org/tutorials/ https://githu…...
深度学习一些简单概念的整理笔记
大概看了一点动手学深度学习,简单整理一些概念。 一些问题 测试结果 Precision-Recall曲线定性分析模型精度average precision(AP) 平均精度 Precision :检索出来的条目中有多大比例是我们需要的。 一些概念 损失函数(loss function&…...
Vue3中引入Element-plus
安装 npm install element-plus --save完整引入 打包后体积很大,适合学习,不适合生产。 此方法对于 vite 和 cli 脚手架创建的vue3均适用 // main.ts import { createApp } from vue //引入element-plus import ElementPlus from element-plus //引入…...
如何查看 Facebook 公共主页的广告数量上限?
作为Facebook的资深人员,了解如何查看公共主页的广告数量上限对于有效管理和优化广告策略至关重要。本文将详细介绍如何轻松查看Facebook公共主页的广告数量上限,以帮助您更好地掌握广告投放策略。 一、什么是Facebook公共主页的广告数量上限?…...
U-Boot移植 (2)- LCD 驱动修改和网络驱动修改
文章目录 1. LCD 驱动修改1.1 修改c文件配置1.2 修改h文件配置1.3 编译测试 2. 网络驱动修改2.1 I.MX6U-ALPHA 开发板网络简介2.2 网络 PHY 地址修改2.3 删除 uboot 中 74LV595 的驱动代码2.4 添加开发板网络复位引脚驱动2.5 更新 PHY 的连接状态和速度2.6 烧写调试2.7 测试一下…...
脑机新手指南(八):OpenBCI_GUI:从环境搭建到数据可视化(下)
一、数据处理与分析实战 (一)实时滤波与参数调整 基础滤波操作 60Hz 工频滤波:勾选界面右侧 “60Hz” 复选框,可有效抑制电网干扰(适用于北美地区,欧洲用户可调整为 50Hz)。 平滑处理&…...
通过Wrangler CLI在worker中创建数据库和表
官方使用文档:Getting started Cloudflare D1 docs 创建数据库 在命令行中执行完成之后,会在本地和远程创建数据库: npx wranglerlatest d1 create prod-d1-tutorial 在cf中就可以看到数据库: 现在,您的Cloudfla…...
java调用dll出现unsatisfiedLinkError以及JNA和JNI的区别
UnsatisfiedLinkError 在对接硬件设备中,我们会遇到使用 java 调用 dll文件 的情况,此时大概率出现UnsatisfiedLinkError链接错误,原因可能有如下几种 类名错误包名错误方法名参数错误使用 JNI 协议调用,结果 dll 未实现 JNI 协…...
STM32标准库-DMA直接存储器存取
文章目录 一、DMA1.1简介1.2存储器映像1.3DMA框图1.4DMA基本结构1.5DMA请求1.6数据宽度与对齐1.7数据转运DMA1.8ADC扫描模式DMA 二、数据转运DMA2.1接线图2.2代码2.3相关API 一、DMA 1.1简介 DMA(Direct Memory Access)直接存储器存取 DMA可以提供外设…...
什么是库存周转?如何用进销存系统提高库存周转率?
你可能听说过这样一句话: “利润不是赚出来的,是管出来的。” 尤其是在制造业、批发零售、电商这类“货堆成山”的行业,很多企业看着销售不错,账上却没钱、利润也不见了,一翻库存才发现: 一堆卖不动的旧货…...
GitHub 趋势日报 (2025年06月06日)
📊 由 TrendForge 系统生成 | 🌐 https://trendforge.devlive.org/ 🌐 本日报中的项目描述已自动翻译为中文 📈 今日获星趋势图 今日获星趋势图 590 cognee 551 onlook 399 project-based-learning 348 build-your-own-x 320 ne…...
C++ 设计模式 《小明的奶茶加料风波》
👨🎓 模式名称:装饰器模式(Decorator Pattern) 👦 小明最近上线了校园奶茶配送功能,业务火爆,大家都在加料: 有的同学要加波霸 🟤,有的要加椰果…...
ZYNQ学习记录FPGA(一)ZYNQ简介
一、知识准备 1.一些术语,缩写和概念: 1)ZYNQ全称:ZYNQ7000 All Pgrammable SoC 2)SoC:system on chips(片上系统),对比集成电路的SoB(system on board) 3)ARM:处理器…...
Oracle实用参考(13)——Oracle for Linux物理DG环境搭建(2)
13.2. Oracle for Linux物理DG环境搭建 Oracle 数据库的DataGuard技术方案,业界也称为DG,其在数据库高可用、容灾及负载分离等方面,都有着非常广泛的应用,对此,前面相关章节已做过较为详尽的讲解,此处不再赘述。 需要说明的是, DG方案又分为物理DG和逻辑DG,两者的搭建…...
【Java基础】向上转型(Upcasting)和向下转型(Downcasting)
在面向对象编程中,转型(Casting) 是指改变对象的引用类型,主要涉及 继承关系 和 多态。 向上转型(Upcasting) ⬆️ 定义 将 子类对象 赋值给 父类引用(自动完成,无需强制转换&…...
