当前位置: 首页 > 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;而…...

docker详细操作--未完待续

docker介绍 docker官网: Docker&#xff1a;加速容器应用程序开发 harbor官网&#xff1a;Harbor - Harbor 中文 使用docker加速器: Docker镜像极速下载服务 - 毫秒镜像 是什么 Docker 是一种开源的容器化平台&#xff0c;用于将应用程序及其依赖项&#xff08;如库、运行时环…...

工程地质软件市场:发展现状、趋势与策略建议

一、引言 在工程建设领域&#xff0c;准确把握地质条件是确保项目顺利推进和安全运营的关键。工程地质软件作为处理、分析、模拟和展示工程地质数据的重要工具&#xff0c;正发挥着日益重要的作用。它凭借强大的数据处理能力、三维建模功能、空间分析工具和可视化展示手段&…...

sqlserver 根据指定字符 解析拼接字符串

DECLARE LotNo NVARCHAR(50)A,B,C DECLARE xml XML ( SELECT <x> REPLACE(LotNo, ,, </x><x>) </x> ) DECLARE ErrorCode NVARCHAR(50) -- 提取 XML 中的值 SELECT value x.value(., VARCHAR(MAX))…...

【AI学习】三、AI算法中的向量

在人工智能&#xff08;AI&#xff09;算法中&#xff0c;向量&#xff08;Vector&#xff09;是一种将现实世界中的数据&#xff08;如图像、文本、音频等&#xff09;转化为计算机可处理的数值型特征表示的工具。它是连接人类认知&#xff08;如语义、视觉特征&#xff09;与…...

Module Federation 和 Native Federation 的比较

前言 Module Federation 是 Webpack 5 引入的微前端架构方案&#xff0c;允许不同独立构建的应用在运行时动态共享模块。 Native Federation 是 Angular 官方基于 Module Federation 理念实现的专为 Angular 优化的微前端方案。 概念解析 Module Federation (模块联邦) Modul…...

uniapp微信小程序视频实时流+pc端预览方案

方案类型技术实现是否免费优点缺点适用场景延迟范围开发复杂度​WebSocket图片帧​定时拍照Base64传输✅ 完全免费无需服务器 纯前端实现高延迟高流量 帧率极低个人demo测试 超低频监控500ms-2s⭐⭐​RTMP推流​TRTC/即构SDK推流❌ 付费方案 &#xff08;部分有免费额度&#x…...

LLM基础1_语言模型如何处理文本

基于GitHub项目&#xff1a;https://github.com/datawhalechina/llms-from-scratch-cn 工具介绍 tiktoken&#xff1a;OpenAI开发的专业"分词器" torch&#xff1a;Facebook开发的强力计算引擎&#xff0c;相当于超级计算器 理解词嵌入&#xff1a;给词语画"…...

【JavaSE】绘图与事件入门学习笔记

-Java绘图坐标体系 坐标体系-介绍 坐标原点位于左上角&#xff0c;以像素为单位。 在Java坐标系中,第一个是x坐标,表示当前位置为水平方向&#xff0c;距离坐标原点x个像素;第二个是y坐标&#xff0c;表示当前位置为垂直方向&#xff0c;距离坐标原点y个像素。 坐标体系-像素 …...

如何在最短时间内提升打ctf(web)的水平?

刚刚刷完2遍 bugku 的 web 题&#xff0c;前来答题。 每个人对刷题理解是不同&#xff0c;有的人是看了writeup就等于刷了&#xff0c;有的人是收藏了writeup就等于刷了&#xff0c;有的人是跟着writeup做了一遍就等于刷了&#xff0c;还有的人是独立思考做了一遍就等于刷了。…...

AI+无人机如何守护濒危物种?YOLOv8实现95%精准识别

【导读】 野生动物监测在理解和保护生态系统中发挥着至关重要的作用。然而&#xff0c;传统的野生动物观察方法往往耗时耗力、成本高昂且范围有限。无人机的出现为野生动物监测提供了有前景的替代方案&#xff0c;能够实现大范围覆盖并远程采集数据。尽管具备这些优势&#xf…...