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

【flask开启进程,前端内容图片化并转pdf-会议签到补充】

flask开启进程,前端内容图片化并转pdf-会议签到补充

  • flask及flask-socketio开启threading
  • 页面内容转图片转pdf
    • 流程
    • 前端主js代码
    • 内容转图片-browser端
    • browser端的同步编程
    • flask的主要功能route,def
  • 总结

用到了pdf,来回数据转发和合成,担心flask卡顿,响应差,于是刚好看到threading方面的介绍,下面详细介绍这两个方面.

flask及flask-socketio开启threading

socketio的开启方法有所差别,不是app中threading=True而是

socketio = SocketIO(app, async_mode='threading',cors_allowed_origins='*' ,message_queue= app.config['REDIS_URL']) 

重新启用WERKZEUG 产生了 ‘WERKZEUG_SERVER_FD’ error,从网上发现,很多werkzeug版本出现过这个问题,而且建议回到2.0.0,可以解决,也不管是什么应用了.其中一个是notebook.我pip list了一下目前版本,3.0.3和flask一个版本.显然回去是不可能的.专门搜素WERKZEUG 和这个错误,在他的官方issu中
https://github.com/pallets/werkzeug/issues/2368

 thanks for the hint. Apparently, it was set in systemd service file, removing that solved the issue.# required to disable Flask debugging banner: "Serving Flask app (lazy loading) ..."
Environment="WERKZEUG_RUN_MAIN=true"

这是作为独立服务的吧.于是我抱着试试看的心里,在flask的配置中加入了这个选项.我想flask的官方文档肯定有相关的说明.而找起来,看似找起来不是太方便.于是瞎猜

app.config['WERKZEUG_RUN_MAIN']=True  # async_mode='threading',

再去启动,不再报错.
测试了gunicorn也正常.到此,虽然flask-socketio限制了worker只能是1,.这样起码threading用起来,会顺畅不少.另外 soketIO这个库,可以启用多worker模式,做一些相关配置.在它的官方说明有说.而且必定可以作为flask,扩展.因为官网也说了.只是目前用起来flask-socketio,不再去测,而且soketIO可以工作的在三种模式,websocket,polling-long.和***忘记了.这个话题暂时到这,下面说转换页面内容,到可打印,而不是可复用.因为是图片,应用性很差.

页面内容转图片转pdf

签到表上次的签到表打印用到了datatable和vue,我这次实现打印的时候, 转到了jquery 操作bootstrap grid.当我费劲把内容呈现在表格样的grid网格里的时候,我发现照样不能打印 说是响应式内容,没有打印风格,于是上路折腾到能打印.中途真想换table. 因为数据从竖排,硬是弄成横竖转换,扯成平的,其实是按照竖向走的,相当于中国古书的样式.从左向右排列,中间还无序分组.12一组,234一组,567一组.每组一个表头.
147
258
369
排列到,一行数据147,一个序列,三个序列.
这个不是重点,只是,完事以后,发现,无法打印.

流程

文件结构组织.
main.html, --含有iframe 和导航
tppint.html- 打印的html原始数据,靠js加载,含有主业务代码,和转换代码
app.py,- 服务器接受图片,转换成pdf,发送回去

Created with Raphaël 2.3.0 main开始,含iframe,src=tpprint tprpint onload加载布局 tprpint $get页面数据 tprpint toPng 转图片 图片格式正常 tprpint fetch post图片 return pdf pdf获取正常 显示可打印的pdf结束 yes no yes no

前端主js代码

在tpprint.html中的处理toPng,和fetch api/putpng2pdf的异步请求代码,指望的main.html调用.结果在自己 onload中,数据加载末尾$.get,处理的结束调用了,我不知道如何捕获他的结束.也许可以重构成返回Promise的函数.很费事的.填空了一下.

 window.asyncprt = async function asyncprt() {// 模拟异步操作,如网络请求return new Promise((resolve, reject) => {var node=document.getElementById('main')domtoimage.toPng(node,{ quality: 1 }).then(async function (dataUrl) {const response = await fetch('./api/putpng2pdf', { method: 'POST', body: JSON.stringify({ dataurl: dataUrl}), headers: { 'Content-Type': 'application/json' } });const arrayBuffer= await response.arrayBuffer()const blob = new Blob([arrayBuffer], { type: 'application/pdf' });// 创建一个URL指向Blob对象const blobUrl = URL.createObjectURL(blob);// 打开新的标签页并导航到PDF文件的URLwindow.open(blobUrl,"_self");resolve('Function finished!');//   window.location.href= "/img/tp.pdf?t="+ Math.floor(Math.random() * 1000);//  console.log( r)});});    };

在文件末尾是,注释掉的,pdf文件暂存,server硬盘,然后,结束来取.后改成,略过存文件,只是一次性,实时的. 直接flask,BytesIO内存托转.回来一个附件是pdf的流.下面是两方面的细节

内容转图片-browser端

上次的签到表转图片用的dom-to-image是6年前的老项目,知道他可以纯js引用,他网站有说明.

var node=document.getElementById('main')domtoimage.toPng(node,{ quality: 1 }).then(async function (dataUrl) {})

可以换toJpeg,也是一样的,数据大一倍.png看似好一点,这个dataurl是base64编码.方便post参数传输,还有一个是blob,方便本地呈现,就和pdf呈现一样.在处理回来数据里有体现blob的处置方式.

browser端的同步编程

涉及到,数据渲染,和图片数据post给后端,有三个事件,分先后.1,onload,2, $.get 取到数据 并给页面赋值 3,.fetch succeed putpng2pdf.将图片dataurl post json给flask API并取得,回程的pdf 附件信息.
上面的[前端主js代码]章节ayncprt是其中的 第三步
第二步末尾,调用asyncprt,我发现 permisA.then(asyncprt)这样是不行的,大概,因为get返回后就已经退出可then了.还有就是,get可能会执行两次.所以设置了一个!done,不一定对的.

var permisA= $.get("/api/gettp",function(data){stas=JSON.parse(data )if (! done  )Object.keys( stas).forEach(function(key) {}asyncprt()})

传参数还不太会,所以就先这样.
第一步的结束,也就是.页面静态内容加载完成,就可以执行第二步.


$().ready(()=>{
$.get("/api/gettp")..................

虽然以上是执行的反顺序.但是可以做为编码的顺序
因为像上传,转换这样的事情,前后端反复调试.前端有个按钮,带个控制台,来看输出,静态tpprint.html长这样.

  <button type="button" class="btn btn-success"  onclick='printme()'> 下载打印</button></li>   
<div   id="main">     
<div class="container"   >
<div class="row" > <div class="col-sm-12"> 
<h3 align='center'>重要会议补充信息登记表</h3><h4 align="right"> 签到2号表 日期:<span id="day"></span></h4> </div> </div></div>
<div class="container" id="gd" ></div></div>

有个难点是默认情况,出来的图片,会有偏移.显示一半.因为对于contain对象, css的语法, dom-to-image 已经无法全部掌握. 不怪它,浏览器也不懂怎么打印.所以,最后

让它纯粹一点,为了防止边距问题,让它固定起来,且加入三个依赖.

<link href="/static/bootstrap.min1.css" rel="stylesheet"  ><script type="text/javascript" src="/js/jquery.min.js"></script><script type="text/javascript" src="/js/dom-to-image.min.js"></script>
<style>#main {display: block;width:1274px;height:778px;background-color: #ffffe1;}</style>

这样大致就能用起来了. 最后,这种嵌套的3步骤顺序之所以会被我整出来.是因为我把它放在 主体中的main.html的iframe下.想在加载,生成图片和pdf后,直接显示出来.在我从iframe外围触发打印按钮时开始, 调用asynprt.结果.只有页面标题,不得已,反复想. 然后发现,在 g e t 完成数据后把 a s y n p r t 放入 . 只要 i f r a m e 加载全部完成 , 就能得到图片 . 在 m a i n . h t m l 无法定位 i f r a m e 中 t p p r i n t 全部完成的时间点 . i f r a m e W i n d o w . o n l o a d 他是表示前置静态内容结束 . 不是 j q u e r y 的 get完成数据后把asynprt放入.只要iframe加载全部完成,就能得到图片.在main.html无法定位iframe中tpprint全部完成的时间点. iframeWindow.onload 他是表示前置静态内容结束.不是jquery的 get完成数据后把asynprt放入.只要iframe加载全部完成,就能得到图片.main.html无法定位iframetpprint全部完成的时间点.iframeWindow.onload他是表示前置静态内容结束.不是jquery.get, 也不是get 里的data. 结束布局.所以外部根本不知道, 替代方案interval(function(),timesec).去间隔查询主体某个元素.这样很笨拙的 操作.
以下是main,html的内容

  <h3 align="center">打印</h3><button   onclick="test()"></button><script> async  function   test() {var iframeWindow = document.getElementById('myif');iframeWindow.contentWindow.location.href="./tpiframe.html" iframeWindow.onload =  async () => {}};</script><iframe id="myif" src='/tpprint.html'  style="display: ; width:1300px;height:800px"></iframe>

最终fetch(‘/api/putpng2pdf’)结束有返回pdf附件后,更新整体 页面

     window.open(blobUrl,"_self");

就在main.html页的iframe中 使用服务器的返回pdf,加载为打印窗口,显示结果如下.
在这里插入图片描述
在iframe所处的main,加入导航是个挺好的办法. ,直接出现打印窗户有点别扭那就没有导航了.
不可避免的是,iframe完成加载的会闪烁到pdf. 因为必须呈现才有图片,有图片才能转pdf.
接下来说flask的后台,实现转换和return send_file

flask的主要功能route,def

依赖 img2pdf,比较完美,什么也不用管,一个covert搞定.要说的是,使用BytesIO,以及,def的return send_file.以及base64. covert可以接受bytes.file_path 或file指针这三种参数.

from flask import send_file
import img2pdf
from io import BytesIO
@app.route("/api/putpng2pdf",methods=['POST'])
def putpng2pdf():data = request.get_json()print()import base64dataraw=base64.b64decode(data['dataurl'][22:])f_io=png2pdf(dataraw)f_io.seek(0)return  send_file(f_io, as_attachment=True,download_name='tp.pdf',mimetype='application/pdf')
def png2pdf(inraw):bytes_io = BytesIO(inraw)out_io= BytesIO()print (len(inraw))#"../img/tp.pdf"# with open(filename ,'wb') as out:out_io.write(img2pdf.convert(bytes_io))return out_io

这里定义png2pdf参数字节数组,返回,BytesIO

out_io.write(img2pdf.convert(bytes_io))
其它:

  1. 取post参数,发送方式是json,可以request.get_json()这样取得. 还有一种方式是form-data.在 p o s t , 或 post ,或 post,.ajax,或fetch中有contentype参数定义.
  2. 在flask的route处理中,base64要把头部去掉,只留纯编码串,经过一次decode,得到原始数据,
  3. 送给png2pdf.
  4. 从pdf,字节bytesIO对象,生成return
    send_file(f_io,as_attachment=True,download_name='tp.pdf',mimetype='application/pdf'),这是直接变成pdf数据流的方式. 以pdf附件方式发送http回应,因为f_io是缓冲区BytesIO内存,模仿文件的对象.所以运行提升必须有download_name参数指定名字. 可见send_file可以发送文件,对象, 字符串文件名.
  5. 这就到了前端处理了
    在收到回应后浏览器的任务是显示pdf.体现在 tpprint.html的fetch url的处理中如下:
  const arrayBuffer= await response.arrayBuffer()const blob = new Blob([arrayBuffer], { type: 'application/pdf' });// 创建一个URL指向Blob对象const blobUrl = URL.createObjectURL(blob);// 打开新的标签页并导航到PDF文件的URLwindow.open(blobUrl,"_self");

大概await就相当于then所以,等待respone.arraryBuffer()然后继续得到Blob.一个浏览器可显示的字节包装类.png和jpeg应该也都有这种方式,这里是pdf,dom-to-image也能转化成blob
这一大段都是baiduAI问答提供的,相当准确,还有注释. 只有提问,js get pdf and show .凑一些词语给一些答案. 犹如复杂的事变条理.绝不会出现我这样的行文.
将来我这样的混乱文笔会是个稀罕玩意.主打一个缭乱.

总结

本文的两个问题,都不大,开始threading和 响应式页面,转打印.其中第一个问题需要,设定参数值,不然报错.第二个问题,很难有系统化的解决方法.都是在试错中前进. 也许有成熟的方法.但是都是成体系,成套路的.这里复述一次页面内容转pdf打印界面的文件结构组织.
main.html, --含有iframe 和导航
tppint.html- 打印的html原始数据,靠js加载,含有主业务代码,和转换代码,
app.py,- 服务器接受图片,转换成pdf,发送回去
然后我就转去画流程图了.画完用了很久,大小朋友,有需求,可以想想,那个流程图.
完毕.

相关文章:

【flask开启进程,前端内容图片化并转pdf-会议签到补充】

flask开启进程,前端内容图片化并转pdf-会议签到补充 flask及flask-socketio开启threading页面内容转图片转pdf流程前端主js代码内容转图片-browser端browser端的同步编程flask的主要功能route,def 总结 用到了pdf,来回数据转发和合成,担心flask卡顿,响应差,于是刚好看到threadi…...

Docker在CentOS上的安装与配置

前言 随着云计算和微服务架构的兴起&#xff0c;Docker作为一种轻量级的容器技术&#xff0c;已经成为现代软件开发和运维中的重要工具。本文旨在为初学者提供一份详尽的指南&#xff0c;帮助他们在CentOS系统上安装和配置Docker及相关组件&#xff0c;如Docker Compose和私有…...

【笔记】开关电源变压器设计 - 工作磁通的选择原则

变压器设计中有一个重要的输入参数&#xff0c;是选定电路工作的磁路参数。涉及到磁场的上下震荡最高幅度。如上图所示。磁场的方向有正负&#xff0c;所以如果电流在越过零点震荡&#xff0c;只考虑半周来和Bs或者Bmax比对即可。Bs,Bmax与特定材料有关。材料给出的最大Bmax,或…...

【VScode】如何在VSCode中配置Python开发环境:从零开始的完整指南

文章目录 前言软件准备软件安装1. 安装Python2. 检查Python是否安装成功3. 安装第三方包4. 安装VSCode 配置VSCode1. 安装Python插件2. 创建项目&#xff0c;配置工作区域3. 编写Python文件4. 配置Python编译设置5. 使用代码格式化工具yapf 更多文章结尾 前言 在当今的编程世界…...

Copy From 勇哥的机器视觉实验项目

形成一种有规划的学习模式,节省时间提升效率。 (一) 单相机标定 (1)halcon的标定助手 这个助手是常用工具,要注意的主要问题是 "品质问题","标定的精度"。 使用的标定板有两种类型,多种材质。选择时要配合灯光来选择材质。 例如玻璃标定板只适合背…...

在IDEA中使用Git

一、准备工作 这里我们使用 Gitee 做例子&#xff0c;使用 SSH 协议。看这个文章前最好看一下《》这个文章&#xff0c;了解一下 SSH。 1、生成秘钥对 首先要到 ~/.ssh 目录下进行操作&#xff0c;因为生成的公钥和私钥一般放在这个目录下&#xff0c;Windows 就是在用户目…...

分布式锁(防止同时操作同一条数据)实现分析

1. deleteLocked 方法&#xff1a; public R deleteLocked(String id, String username) {String examReportUserKey "examReportId_" id "_" username;stringRedisTemplate.delete(examReportUserKey);return R.ok(); } 功能&#xff1a;删除指定用户…...

【已解决,含泪总结】Ubuntu18.04下非root用户Anaconda3卸载重装,conda install终于不再报错

为什么要卸载重装 因为我最初安装的Anaconda3的版本是5.2.0&#xff0c;适合python3.6.5&#xff0c;其下的conda版本是4.5.4 我一开始本着能用则用&#xff0c;毕竟不是很懂的原则&#xff0c;尽量不要卸掉重来 但。。。bug像滚雪球一样&#xff0c;越来越多 conda install指…...

大语言模型(LLM)量化基础知识(一)

请大家关注我的知乎博客&#xff1a;- 派神 - - 知乎 随着大型语言模型 (LLM) 的参数数量的增长,与其支持硬件&#xff08;加速器内存&#xff09;增长速度之间的差距越来越大&#xff0c;如下图所示&#xff1a; 上图显示&#xff0c;从 2017 年到 2022 年&#xff0c;语言模…...

hadoop面试题

一、单项选择题 1、目前&#xff0c;Hadoop的最高版本是哪个&#xff08; A &#xff09; A、Hadoop3.x B、Hadoop2.x C、Hadoop4.x D、Hadoop1.x 2、大数据的4V特征是指? &#xff08; B &#xff09; A、数据量大(Volume)、类型繁多(Variety)、价值密度低(Va…...

mysql 安装 windows

新版安装 新版本安装 如果出现initializing database无法安装 则用我当前版本传送门 如MySQL 安装时没有developer default 选项 解决方法传送门 如果上述还不行 可以选择full 汉化下载 传送门...

24下软考中级网络工程师考前必背22页

数据中心选址原则 1、地理位置&#xff1a;备选址地点发生自然灾害的概率和频率、环境危害因素以及气候因素 2、电力能源供应&#xff1a;可用性、成本因素 3、通讯基础设施&#xff1a;光纤主干线路及其距数据中心选址的距离、光纤类型、服务运营商的类型及其支持的服务模式…...

Java类和对象(下篇)

今天接着学习类和对象(苦笑)(苦笑)(苦笑) 1. 封装 1.1 封装的概念 面向对象程序三大特性&#xff1a;封装、继承、多态。 而类和对象阶段&#xff0c;主要研究的就是封装特性。 何为封装呢&#xff1f;简单来说就是套壳屏蔽细节。 举例&#xff1a;对于计算机使用者而言&am…...

k8s图形化显示(KRM)

在master节点 kubectl get po -n kube-system 这个命令会列出 kube-system 命名空间中的所有 Pod 的状态和相关信息&#xff0c;比如名称、状态、重启次数等。 systemctl status kubelet #查看kubelet状态 yum install git #下载git命令 git clone https://gitee.com/duk…...

apache poi 实现下拉框联动校验

apache poi 提供了 DataValidation​ 接口 让我们可以轻松实现 Excel 下拉框数据局校验。但是下拉框联动校验是无法直接通过 DataValidation ​实现&#xff0c;所以我们可以通过其他方式间接实现。 ‍ 步骤如下&#xff1a; 创建一个隐藏 sheet private static void create…...

【canal 中间件】canal 实时监听 binlog

文章目录 一、安装 MySQL1.1 启动 mysql 服务器1.2 开启 Binlog 写入功能1.2.1创建 binlog 配置文件1.2.2 修改配置文件权限1.2.3 挂载配置文件1.2.4 检测 binlog 配置是否成功 1.3 创建账户并授权 二、安装 canal2.1 安装 canal-admin(可选)2.1.1 启动 canal-admin 容器2.1.2 …...

JVM垃圾收集算法、对应收集器和选择建议

如果说垃圾收集算法是内存回收的方法论&#xff0c;那么垃圾收集器就是内存回收的具体实现。 到目前为止还没有最好的垃圾收集器出现&#xff0c;也没万能的垃圾收集器。实际使用中&#xff0c;根据具体应用场景选择合适的垃圾收集器。 1、垃圾收集算法 垃圾收集算法可以从高…...

如何在算家云搭建Aatrox-Bert-VITS2(音频生成)

一、模型介绍 ‌ Aatrox - Bert -VITS2 模型是一种基于深度学习的语音合成系统&#xff0c;结合了 BERT 的预训练能力和 VITS2 的微调技术&#xff0c;旨在实现高质量的个性化语音合成。 二、模型搭建流程 1. 创建容器实例 进入算家云的“应用社区”&#xff0c;点击搜索找到…...

ceph灾备之cephfs snapshot mirror和rsync对比

背景 最近要做ceph集群之间的灾备功能&#xff0c;主要讨论文件存储&#xff0c;因为ceph集群容量越来越大&#xff0c;接入的业务也越来越多&#xff0c;一旦出现故障&#xff0c;恢复时间都是小时级(根据经验每年都会出现几次这种事故)&#xff0c;对于核心业务无法接受&…...

【工具分享】Plutocrypt勒索病毒解密工具

前言 Plutocrypt勒索软件首次出现在2021年&#xff0c;作为CryptoJoker勒索软件的变种。该恶意软件通过钓鱼邮件和恶意链接传播&#xff0c;主要针对个人和小型企业用户。Plutocrypt使用了.NET框架开发&#xff0c;并依赖AES-256和RSA-4096的加密算法来加密受害者的文件。与Cr…...

浏览器访问 AWS ECS 上部署的 Docker 容器(监听 80 端口)

✅ 一、ECS 服务配置 Dockerfile 确保监听 80 端口 EXPOSE 80 CMD ["nginx", "-g", "daemon off;"]或 EXPOSE 80 CMD ["python3", "-m", "http.server", "80"]任务定义&#xff08;Task Definition&…...

基于算法竞赛的c++编程(28)结构体的进阶应用

结构体的嵌套与复杂数据组织 在C中&#xff0c;结构体可以嵌套使用&#xff0c;形成更复杂的数据结构。例如&#xff0c;可以通过嵌套结构体描述多层级数据关系&#xff1a; struct Address {string city;string street;int zipCode; };struct Employee {string name;int id;…...

synchronized 学习

学习源&#xff1a; https://www.bilibili.com/video/BV1aJ411V763?spm_id_from333.788.videopod.episodes&vd_source32e1c41a9370911ab06d12fbc36c4ebc 1.应用场景 不超卖&#xff0c;也要考虑性能问题&#xff08;场景&#xff09; 2.常见面试问题&#xff1a; sync出…...

前端倒计时误差!

提示:记录工作中遇到的需求及解决办法 文章目录 前言一、误差从何而来?二、五大解决方案1. 动态校准法(基础版)2. Web Worker 计时3. 服务器时间同步4. Performance API 高精度计时5. 页面可见性API优化三、生产环境最佳实践四、终极解决方案架构前言 前几天听说公司某个项…...

23-Oracle 23 ai 区块链表(Blockchain Table)

小伙伴有没有在金融强合规的领域中遇见&#xff0c;必须要保持数据不可变&#xff0c;管理员都无法修改和留痕的要求。比如医疗的电子病历中&#xff0c;影像检查检验结果不可篡改行的&#xff0c;药品追溯过程中数据只可插入无法删除的特性需求&#xff1b;登录日志、修改日志…...

基于Flask实现的医疗保险欺诈识别监测模型

基于Flask实现的医疗保险欺诈识别监测模型 项目截图 项目简介 社会医疗保险是国家通过立法形式强制实施&#xff0c;由雇主和个人按一定比例缴纳保险费&#xff0c;建立社会医疗保险基金&#xff0c;支付雇员医疗费用的一种医疗保险制度&#xff0c; 它是促进社会文明和进步的…...

MySQL 8.0 OCP 英文题库解析(十三)

Oracle 为庆祝 MySQL 30 周年&#xff0c;截止到 2025.07.31 之前。所有人均可以免费考取原价245美元的MySQL OCP 认证。 从今天开始&#xff0c;将英文题库免费公布出来&#xff0c;并进行解析&#xff0c;帮助大家在一个月之内轻松通过OCP认证。 本期公布试题111~120 试题1…...

2023赣州旅游投资集团

单选题 1.“不登高山&#xff0c;不知天之高也&#xff1b;不临深溪&#xff0c;不知地之厚也。”这句话说明_____。 A、人的意识具有创造性 B、人的认识是独立于实践之外的 C、实践在认识过程中具有决定作用 D、人的一切知识都是从直接经验中获得的 参考答案: C 本题解…...

学校时钟系统,标准考场时钟系统,AI亮相2025高考,赛思时钟系统为教育公平筑起“精准防线”

2025年#高考 将在近日拉开帷幕&#xff0c;#AI 监考一度冲上热搜。当AI深度融入高考&#xff0c;#时间同步 不再是辅助功能&#xff0c;而是决定AI监考系统成败的“生命线”。 AI亮相2025高考&#xff0c;40种异常行为0.5秒精准识别 2025年高考即将拉开帷幕&#xff0c;江西、…...

智能AI电话机器人系统的识别能力现状与发展水平

一、引言 随着人工智能技术的飞速发展&#xff0c;AI电话机器人系统已经从简单的自动应答工具演变为具备复杂交互能力的智能助手。这类系统结合了语音识别、自然语言处理、情感计算和机器学习等多项前沿技术&#xff0c;在客户服务、营销推广、信息查询等领域发挥着越来越重要…...