当前位置: 首页 > news >正文

小程序开发实战:PDF转换为图片工具开发

目录

一、开发思路

1.1 申请微信小程序

1.2 编写后端接口

1.3 后端接口部署

1.4 微信小程序前端页面开发

1.5 运行效果

1.6 小程序部署上线


图片

今天给大家分享小程序开发系列,PDF转换为图片工具的开发实战,感兴趣的朋友可以一起来学习一下!

一、开发思路

  • 申请微信小程序

  • 编写后端接口

  • 后端接口部署

  • 微信小程序前端页面开发

  • 微信小程序部署上线

1.1 申请微信小程序

关于如何申请微信小程序这里就不过多介绍了,大家可以参考腾讯官方的文档,里面介绍的非常详细。

图片

1.2 编写后端接口

这里使用Java编程语言的SpringBoot框架来快速搭建WebAPI服务。因为涉及到PDF转换为图片,这里使用spire.pdf来实现。首先引入依赖项

      <dependency><groupId>e-iceblue</groupId><artifactId>spire.pdf.free</artifactId><version>2.6.3</version><scope>provided</scope></dependency>

新建PdfUtils.java工具类库用来实现PDF转换为图片的功能

思路:通过微信小程序传递过来的文件转换为InputStream输出流,然后保存到服务器端,因为PDF可能涉及有多页,每一页单独为一个图片文件,然后调用图片拼接的方法实现所有页面图片合并为一张长图。注意:免费的spire.pdf支持10页之内的pdf转换,大家如果更高需求,可以考虑购买收费版。

主要代码如下:转换方法主函数

 
   /*** 根据文件流转换为图片** @param stream* @return*/public String pdftoimage(InputStream stream, String fileNameOld) {Date currentDate = new Date();SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd_HHmmss_SSS"); // 指定日期格式,包含毫秒String formattedDate = sdf.format(currentDate);String pathPath = "/mnt/files/" + formattedDate + "_" + fileNameOld;// 4、最终生成的doc所在的目录,默认是和引入的一个地方,开源时对外提供下载的接口。saveInputStreamToFile(stream, pathPath);String fileName = "result" + formattedDate + ".png";String desPath = "/mnt/files/" + fileName; // 构造文件名String sux = fileNameOld + "_" + formattedDate;// 临时文件前缀boolean result = false;try {// 0、判断输入的是否是pdf文件//第一步:判断输入的是否合法//boolean flag = isPDFFile(srcPath);//第二步:在输入的路径下新建文件夹boolean flag1 = create();if (flag1) {// 1、加载pdfPdfDocument pdf = new PdfDocument();//pdf.loadFromStream(stream);pdf.loadFromFile(pathPath);PdfPageCollection num = pdf.getPages();// 2、如果pdf的页数小于11,那么直接进行转化if (num.getCount() <= 10) {try {for (int i = 0; i < pdf.getPages().getCount(); i++) {BufferedImage image = pdf.saveAsImage(i, PdfImageType.Bitmap, 300, 300);String imgTemp = imgPath + sux + (i + 1) + ".png"; // 构造输出文件路径ImageIO.write(image, "PNG", new File(imgTemp));}pdf.close();System.out.println("PDF转图片完成!");MergeWordDocument.mergeImage(imgPath, desPath, sux);clearFiles(imgPath, formattedDate);clearFiles(pathPath, formattedDate);} catch (IOException e) {e.printStackTrace();System.out.println("PDF转图片失败: " + e.getMessage());}}// 3、否则输入的页数比较多,就开始进行切分再转化else {try {for (int i = 0; i < 10; i++) {BufferedImage image = pdf.saveAsImage(i, PdfImageType.Bitmap, 300, 300);String imgTemp = imgPath + sux + (i + 1) + ".png"; // 构造输出文件路径ImageIO.write(image, "PNG", new File(imgTemp));}pdf.close();System.out.println("PDF转图片完成!");MergeWordDocument.mergeImage(imgPath, desPath, sux);} catch (IOException e) {e.printStackTrace();System.out.println("PDF转图片失败: " + e.getMessage());} finally {//clearFiles(imgPath);clearFiles(pathPath, formattedDate);}}} else {System.out.println("输入的不是pdf文件");fileName = "";return fileName;}} catch (Exception e) {fileName = "";e.printStackTrace();} finally {//4、把刚刚缓存的split和doc删除if (result == true) {clearFiles(pathPath, formattedDate);clearFiles(splitPath, formattedDate);clearFiles(docPath, formattedDate);}}return fileName;
}

保存PDF文件到本地,然后使用后删除

/**
* 保存原始的pdf文件为了方便拆分
*
* @param inputStream
* @param filePath
*/
public static void saveInputStreamToFile(InputStream inputStream, String filePath) {// 使用try-with-resources自动关闭流try (FileOutputStream outputStream = new FileOutputStream(new File(filePath))) {byte[] buffer = new byte[1024];int length;// 读取输入流并写入到输出流while ((length = inputStream.read(buffer)) > 0) {outputStream.write(buffer, 0, length);}System.out.println("文件保存成功!");} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}
}

多张图片合并逻辑

/**
* 多张图片合并之后的逻辑
* @param imagePath
* @param desPath
* @return
*/
public static boolean mergeImage(String imagePath, String desPath,String sux) {try {File folder = new File(imagePath);// 包含文件前缀的文件 简单解决并发的问题File[] imageFiles = folder.listFiles((dir, name) ->(name.toLowerCase().endsWith(".png") || name.toLowerCase().endsWith(".jpg") && name.contains(sux)));if (imageFiles != null && imageFiles.length > 0) {int maxWidth = 0;int totalHeight = 0;// 预先计算最大宽度和总高度for (File imageFile : imageFiles) {BufferedImage image = ImageIO.read(imageFile);maxWidth = Math.max(maxWidth, image.getWidth());totalHeight += image.getHeight();image.flush(); // 尝试释放资源}// 创建合并后的图片,仅初始化一次BufferedImage mergedImage = new BufferedImage(maxWidth, totalHeight, BufferedImage.TYPE_INT_ARGB);Graphics2D g2d = mergedImage.createGraphics();int currentY = 0;for (File imageFile : imageFiles) {BufferedImage image = ImageIO.read(imageFile);g2d.drawImage(image, 0, currentY, null);currentY += image.getHeight();image.flush(); // 处理完后释放当前图片资源}g2d.dispose();// 保存合并后的图片ImageIO.write(mergedImage, "PNG", new File(desPath));System.out.println("图片合并完成!");for (File file : imageFiles){if (file.exists()) {if (file.delete()) {System.out.println("文件 " + file.getName() + " 已被删除");} else {System.out.println("无法删除文件 " + file.getName());}} else {System.out.println("文件 " + file.getName() + " 不存在");}}} else {System.out.println("输入文件夹中没有图片文件!");}} catch (IOException e) {e.printStackTrace();System.out.println("图片合并失败: " + e.getMessage());}return true;
}

新建控制器PdfApi.java

用来接收小程序调用传递过来的参数,需要判断传递过来的文件是否为图片格式,然后调用转换方法即可。

 /*** pdf转图片 多页转一张图* @param uploadFile* @return* @throws IOException*/@PostMapping("pdfconvertimage")public String upload(@RequestPart("file") MultipartFile uploadFile) throws IOException {if (null == uploadFile) {return null;}// BMP、JPG、JPEG、PNG、GIFString fileName = uploadFile.getOriginalFilename().toLowerCase();if (!fileName.endsWith(".pdf")) {return null;}//String image= PdfUtils.pdf(uploadFile.getInputStream(),Integer.valueOf(type));String image= PdfUtils.pdfToPng(uploadFile.getInputStream(),fileName);// 返回响应实体return image;}
 

1.3 后端接口部署

因为微信小程序调用第三方接口需要https域名形式,所以接口开发完成后,需要部署到云服务器,然后申请域名、申请SSL证书,确保接口可以通过https域名正常访问。并且在微信小程序开发设置配置request合法域名白名单,保证接口可以调通。

图片

1.4 微信小程序前端页面开发

打开微信开发者工具,然后微信小程序管理员扫码登录自己的微信小程序。这里主要给大家贴出主要的代码以及实现思路。具体界面如下:

上传方式:支持微信会话文件上传、直接输入PDF文件的URL,转换成功后可以点击下载按钮进行下载图片。

图片

wxml文件代码如下:


<view style="text-align: center;">
<image style="width: 98%;"  src="推广图片"></image>
</view>
<view class="selectSection"><text class="textmag">上传方式:</text><radio-group bindchange="radioChange" class="radio-group"><label class="radio" wx:for="{{direction}}" wx:key="i"><icon class="radioIcon {{item.checked?'actIcon':''}}"></icon><radio checked="{{item.checked}}" value="{{item.name}}"></radio>{{item.value}}</label></radio-group>
</view>
<view class="container"><view wx:if="{{directionType==1}}" class="item"> <button style="width: 120px;" class="butss" bindtap="chooseFile">上传pdf文件</button></view><view wx:if="{{directionType==2}}" class="item"> <button style="width: 120px;" class="butss" bindtap="chooseFileNew">生成图片</button></view><view class="item"> <button style="width: 90px;" class="butss" bindtap="saveTap">下载</button></view><view class="item"> <button style="width: 90px;" class="butss" bindtap="clearTap">清空</button></view>
</view><view style="padding: 20px;"><span style="color: red;font-size: 12px;">温馨提示:目前支持10页以内的pdf文件转换</span>
</view>
<view><textarea  auto-height bindinput="handleInput" class="input-content" value="{{uploadUrl}}"  placeholder="请输入pdf文件url" wx:if="{{directionType==2}}"></textarea>
</view><view class="instruction"> <span style="color: black;padding-left: 10px;">结果文件:{{data}}</span>
</view>

js主要代码:

 // 选择微信会话文件 然后直接调用上传接口chooseFile: function () {var that = this;wx.showLoading({title: '图片上传处理中,请稍后...',});wx.chooseMessageFile({count: 1,type: 'file',extension: ['pdf'], // 限定选择的文件格式为.doc, .docx, .pdfsuccess: function (res) {const tempFilePath = res.tempFiles[0].path;if (res.tempFiles[0].size > 10 * 1024 * 1024) { // 限定文件大小为2MBwx.showToast({title: '文件大小超过限制,请选择小于10MB的文件',icon: 'none'});return;}that.setData({pdfPath: tempFilePath                })wx.uploadFile({url: '后端接口API',filePath: tempFilePath,formData: { },name: 'file',success: function (res) {if (res.statusCode == "200") { that.setData({imageUrl: res.data,// 直接可以访问的urldata: res.data}); wx.showToast({title: '转换成功',icon: 'success',duration: 2000});} else {wx.showToast({title: '转换失败,请联系管理员',icon: 'none',duration: 2000});}},fail: function (res) {wx.showToast({title: '上传失败',icon: 'none',duration: 2000});}});},fail: function (res) {console.error('选择文件失败', res);wx.showToast({title: '选择文件失败',icon: 'none',duration: 2000});}});},// 下载按钮事件saveTap: function () {if (this.data.imageUrl) {wx.downloadFile({url: this.data.imageUrl,success: function (res) {if (res.statusCode === 200) {var filePath = res.tempFilePath;// 调用保存图片方法wx.saveImageToPhotosAlbum({filePath: filePath,success: function (res) {wx.showToast({title: '保存成功',icon: 'success',duration: 2000});},fail: function (err) {console.error(err);wx.showToast({title: '保存失败',icon: 'none',duration: 2000});}});}},fail: function (err) {console.error(err);wx.showToast({title: '下载失败',icon: 'none',duration: 2000});}});} else {wx.showToast({title: '请先上传pdf文件,转换成功后再保存',icon: 'none',duration: 2000});}},


1.5 运行效果

选择pdf文件上传

图片

转换成功之后的结果文件如下:

图片

然后可以点击下载按钮下载图片文件。整体转还原度还是很高的。

1.6 小程序部署上线

该步骤对于小程序开发的朋友来说,还是非常简单的,这里就不过多介绍了,大家有问题的话,欢迎沟通交流!

相关文章:

小程序开发实战:PDF转换为图片工具开发

目录 一、开发思路 1.1 申请微信小程序 1.2 编写后端接口 1.3 后端接口部署 1.4 微信小程序前端页面开发 1.5 运行效果 1.6 小程序部署上线 今天给大家分享小程序开发系列&#xff0c;PDF转换为图片工具的开发实战&#xff0c;感兴趣的朋友可以一起来学习一下&#xff01…...

我有两台120kw充电桩一天能赚多少钱

&#xff08;当前是理想状态下&#xff0c;当然还要看场地费用&#xff0c;还有物业&#xff0c;变压器&#xff0c;等等&#xff09; ———————————————————— ———————————————————— 要计算两台120kW充电桩能赚多少钱&#xff0c;我们…...

深入了解 Android 中的命名空间:`xmlns:tools` 和其他常见命名空间

在 Android 开发中&#xff0c;xmlns &#xff08;.xml的namespace&#xff09;命名空间是一个非常重要的概念。通过引入不同的命名空间&#xff0c;可以使用不同的属性来设计布局、设置工具属性或者支持自定义视图等。除了 xmlns:tools 以外&#xff0c;还有很多常见的命名空间…...

stable-zero123模型构建指南

一、介绍 stabilityai出品&#xff0c;能够对有简单背景的物体进行三维视角图片的生成&#xff0c;简单来说也就是通过调整变换观察的视角生成对应视角的图片。 本项目通过comfyui实现。 二、容器构建说明 1. 部署ComfyUI &#xff08;1&#xff09;使用命令克隆ComfyUI g…...

算法题解记录32+++最长连续序列(百题筑基)

你们好&#xff0c;我是蚊子码农&#xff0c;好久不见。由于秋招求职的繁琐事情&#xff0c;我有很长一段时间没更新博客&#xff0c;希望我的粉丝们能够谅解。 秋招我拿到了一些offer&#xff0c;最终决定去一个主要做“网络安全”业务的公司工作&#xff0c;也许明天会更好&a…...

全球知名度最高的华人起名大师颜廷利:世界顶级思想哲学教育家

全国给孩子起名最好的大师颜廷利教授在其最新的哲学探索中&#xff0c;提出了《升命学说》这一前沿理论观点&#xff0c;该理论不仅深刻地回应了古今中外众多哲学流派和思想体系的精髓&#xff0c;还巧妙地融合了实用主义、理想主义以及经验主义的核心理念。通过这一独特的视角…...

Flink Rest API

REST API | Apache Flink Flink官网API 通过curl 或者Rest API工具测试web UI对应的接口返回信息 Flink 提交yarn任务 ./bin/flink run -t yarn-per-job historyServer ../bin/historyserver.sh start...

Zig 语言通用代码生成器:逻辑,冒烟测试版发布二

Zig 语言通用代码生成器&#xff1a;逻辑&#xff0c;冒烟测试版发布二 Zig 语言是一种新的系统编程语言&#xff0c;其生态位类同与 C&#xff0c;是前一段时间大热的 rust 语言的竞品。它某种意义上的确非常像 rust&#xff0c;尤其是在开发过程中无穷无尽抛错的过程&#x…...

mysql 通过GROUP BY 聚合并且拼接去重另个字段

我的需求&#xff1a; 我想知道同一个手机号出现几次&#xff0c;并且手机号出现在哪些地方。下面是要的效果。 源数据: CREATE TABLE bank (id bigint(20) unsigned NOT NULL AUTO_INCREMENT,user_id int(11) NOT NULL DEFAULT 0,tel varchar(255) COLLATE utf8mb4_unicode_…...

Java应用程序的测试覆盖率之设计与实现(一)-- 总体设计

一、背景 作为测试,如何保证开发人员提交上来的代码都被测试覆盖到,是衡量测试质量的一个重要指标。 本系列文章将要说一说,如何搭建一套测试覆盖率的系统。 包括以下内容: jacoco agent采集执行覆盖率数据jacoco climaven集成jacoco:jacoco-maven-pluginant集成jacoco:…...

Unity C#脚本的热更新

以下内容是根据Unity 2020.1.0f1版本进行编写的   目前游戏开发厂商主流还是使用lua框架来进行热更&#xff0c;如xlua&#xff0c;tolua等&#xff0c;也有的小游戏是直接整包更新&#xff0c;这种小游戏的包体很小&#xff0c;代码是用C#写的&#xff1b;还有的游戏就是通过…...

监督学习之逻辑回归

逻辑回归&#xff08;Logistic Regression&#xff09; 逻辑回归是一种用于二分类&#xff08;binary classification&#xff09;问题的统计模型。尽管其名称中有“回归”二字&#xff0c;但逻辑回归实际上用于分类任务。它的核心思想是通过将线性回归的输出映射到一个概率值…...

深度优先算法(DFS)洛谷P1683-入门

虽然洛谷是有题解的,但是你如果直接看得懂题解,你也不会来看这篇文章.. 这些代码均是我记录自身成长的记录,有写的不好的地方请谅解&#xff01; 先上代码&#xff1a; #include <iostream> #include <vector> #include<iomanip> #include<cstdio&…...

Python数据分析基础

本文介绍了Python在数据分析中的应用&#xff0c;包括数据读取、清洗、处理和分析的基本操作。通过使用Pandas和Numpy库&#xff0c;我们可以高效地处理大量数据&#xff0c;并利用Matplotlib和Seaborn库进行数据可视化。 1. 引言 Python因其简洁的语法和强大的库支持&#x…...

《企业自设2-软件测试》线下课day3: 006扩展虚拟机

1.win11 修改hosts无权限 分别再cmd终端输入以下两行代码&#xff1a; C:\Windows\System32\drivers\etcnotepad hosts 2.先保存快照&#xff01;&#xff01;&#xff01; 3.关闭虚拟机&#xff0c;将内存&#xff0c;CPU进行修改 就是再这个位置修改&#xff1a; 4.运…...

配置和排查 Lombok 在 IDEA 中使用的详细步骤

在日常开发中&#xff0c;Java 代码常常需要大量的样板代码&#xff0c;比如 getter、setter、toString 等方法。Lombok 是一个 Java 库&#xff0c;可以通过注解的方式&#xff0c;自动生成这些常见的代码&#xff0c;从而让代码更加简洁、清晰。比如&#xff0c;我们可以通过…...

JavaWeb合集18-接口管理Swager

十八、接口管理 1、Swager 使用Swagger你只需要按照它的规范去定义接口及接口相关的信息&#xff0c;就可以做到生成接口文档&#xff0c;以及在线接口调试页面。 官网: https://swagger.io/ Knife4j是为Java MVC框架集成Swagger生成Api文档的增强解决方案。 <dependency&g…...

背包九讲——二维费用背包问题

目录 二维费用背包问题 问题描述&#xff1a; 解决方法&#xff1a; 方法一&#xff1a; 代码实现&#xff1a; 方法二&#xff1a; 代码实现&#xff1a; 背包问题第五讲——二维费用背包问题 背包问题是一类经典的组合优化问题&#xff0c;通常涉及在限定容量的背包中…...

【mysql进阶】4-7. 通用表空间

通⽤表空间 - General Tablespace 1 通⽤表空间的作⽤和特性&#xff1f; ✅ 解答问题 通⽤表空间是使⽤ CREATE tablespace 语法创建的共享InnoDB表空间 通⽤表空间能够存储多个表的数据&#xff0c;与系统表空间类似也是共享表空间&#xff1b; 服务器运⾏时会把表空间元数…...

2024 年互联网大厂 1300 多道 JAVA 面试题汇总,包含了程序员的所有技术点

作为一个 Java 程序员&#xff0c;你平时总是陷在业务开发里&#xff0c;每天噼里啪啦忙敲着代码&#xff0c;上到系统开发&#xff0c;下到 Bug 修改&#xff0c;你感觉自己无所不能。然而偶尔的一次聚会&#xff0c;你听说和自己一起出道的同学早已经年薪 50 万&#xff0c;而…...

装饰模式(Decorator Pattern)重构java邮件发奖系统实战

前言 现在我们有个如下的需求&#xff0c;设计一个邮件发奖的小系统&#xff0c; 需求 1.数据验证 → 2. 敏感信息加密 → 3. 日志记录 → 4. 实际发送邮件 装饰器模式&#xff08;Decorator Pattern&#xff09;允许向一个现有的对象添加新的功能&#xff0c;同时又不改变其…...

java_网络服务相关_gateway_nacos_feign区别联系

1. spring-cloud-starter-gateway 作用&#xff1a;作为微服务架构的网关&#xff0c;统一入口&#xff0c;处理所有外部请求。 核心能力&#xff1a; 路由转发&#xff08;基于路径、服务名等&#xff09;过滤器&#xff08;鉴权、限流、日志、Header 处理&#xff09;支持负…...

Vue3 + Element Plus + TypeScript中el-transfer穿梭框组件使用详解及示例

使用详解 Element Plus 的 el-transfer 组件是一个强大的穿梭框组件&#xff0c;常用于在两个集合之间进行数据转移&#xff0c;如权限分配、数据选择等场景。下面我将详细介绍其用法并提供一个完整示例。 核心特性与用法 基本属性 v-model&#xff1a;绑定右侧列表的值&…...

循环冗余码校验CRC码 算法步骤+详细实例计算

通信过程&#xff1a;&#xff08;白话解释&#xff09; 我们将原始待发送的消息称为 M M M&#xff0c;依据发送接收消息双方约定的生成多项式 G ( x ) G(x) G(x)&#xff08;意思就是 G &#xff08; x ) G&#xff08;x) G&#xff08;x) 是已知的&#xff09;&#xff0…...

ElasticSearch搜索引擎之倒排索引及其底层算法

文章目录 一、搜索引擎1、什么是搜索引擎?2、搜索引擎的分类3、常用的搜索引擎4、搜索引擎的特点二、倒排索引1、简介2、为什么倒排索引不用B+树1.创建时间长,文件大。2.其次,树深,IO次数可怕。3.索引可能会失效。4.精准度差。三. 倒排索引四、算法1、Term Index的算法2、 …...

Xen Server服务器释放磁盘空间

disk.sh #!/bin/bashcd /run/sr-mount/e54f0646-ae11-0457-b64f-eba4673b824c # 全部虚拟机物理磁盘文件存储 a$(ls -l | awk {print $NF} | cut -d. -f1) # 使用中的虚拟机物理磁盘文件 b$(xe vm-disk-list --multiple | grep uuid | awk {print $NF})printf "%s\n"…...

JVM虚拟机:内存结构、垃圾回收、性能优化

1、JVM虚拟机的简介 Java 虚拟机(Java Virtual Machine 简称:JVM)是运行所有 Java 程序的抽象计算机,是 Java 语言的运行环境,实现了 Java 程序的跨平台特性。JVM 屏蔽了与具体操作系统平台相关的信息,使得 Java 程序只需生成在 JVM 上运行的目标代码(字节码),就可以…...

人机融合智能 | “人智交互”跨学科新领域

本文系统地提出基于“以人为中心AI(HCAI)”理念的人-人工智能交互(人智交互)这一跨学科新领域及框架,定义人智交互领域的理念、基本理论和关键问题、方法、开发流程和参与团队等,阐述提出人智交互新领域的意义。然后,提出人智交互研究的三种新范式取向以及它们的意义。最后,总结…...

[免费]微信小程序问卷调查系统(SpringBoot后端+Vue管理端)【论文+源码+SQL脚本】

大家好&#xff0c;我是java1234_小锋老师&#xff0c;看到一个不错的微信小程序问卷调查系统(SpringBoot后端Vue管理端)【论文源码SQL脚本】&#xff0c;分享下哈。 项目视频演示 【免费】微信小程序问卷调查系统(SpringBoot后端Vue管理端) Java毕业设计_哔哩哔哩_bilibili 项…...

MySQL的pymysql操作

本章是MySQL的最后一章&#xff0c;MySQL到此完结&#xff0c;下一站Hadoop&#xff01;&#xff01;&#xff01; 这章很简单&#xff0c;完整代码在最后&#xff0c;详细讲解之前python课程里面也有&#xff0c;感兴趣的可以往前找一下 一、查询操作 我们需要打开pycharm …...