【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文件的URL
     window.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 base64
    dataraw=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文件的URL
     window.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,发送回去
然后我就转去画流程图了.画完用了很久,大小朋友,有需求,可以想想,那个流程图.
完毕.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/910781.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

R7:糖尿病预测模型优化探索

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 一、实验目的&#xff1a; 探索本案例是否还有进一步优化的空间 二、实验环境&#xff1a; 语言环境&#xff1a;python 3.8编译器&#xff1a;Jupyter notebo…

张氏宗谱序言白话文翻译

序言&#xff1a; 回想千家有赤松子的传承&#xff0c;张家有 “百忍” 的风范。感慨因迁徙和战乱、水灾之苦&#xff0c;远居他乡而失去了家族秩序。想起自从从泗州来到淮安&#xff0c;安家在安东县东北乡众湖荡之地。&#xff08;这里可能在回忆家族的迁徙历史&#xff09;…

从0开始学习Linux——Yum工具

往期目录&#xff1a; 从0开始学习Linux——简介&安装 从0开始学习Linux——搭建属于自己的Linux虚拟机 从0开始学习Linux——文本编辑器 上一个章节我们简单了解了Linux中常用的一些文本编辑器&#xff0c;本次教程我们将学习yum工具。 一、Yum简介 Yum&#xff08;全名…

推荐一款基于Flash的交互式园林设计工具:Garden Planner

Garden Planner是一款由Artifact Interactive开发的基于Flash的交互式园林设计工具。它允许用户以拖放的方式安排植物、树木、建筑物和各种对象&#xff0c;使园林规划变得简单直观。此外&#xff0c;Garden Planner提供工具来快速创建铺路、路径和围栏&#xff0c;帮助用户设计…

WinForms 中使用 MVVM 模式构建应用:实现登录页面、页面导航及 SQLite 数据库连接完整框架搭建过程

前言 在传统的 WinForms 应用程序开发中&#xff0c;很多开发者使用事件驱动的设计模式&#xff0c;直接将业务逻辑编写在界面代码中。然而&#xff0c;随着应用程序的复杂性增加&#xff0c;单一的界面文件变得臃肿&#xff0c;难以测试和维护。借鉴 WPF 中 MVVM&#xff08;…

诗林工作室(编号:mb0003)分享:Finbiz自适应响应式网页设计模版,适用于前端设计、博客、官网等多类型开发模版

本设计模版来自外网&#xff0c;为HTML类型的模版&#xff0c;色彩多样&#xff0c;适合Web开发人员做前端站点设计参考使用。全站模版倾向于官网设计、自主博客等多行业的平台模版开发&#xff0c;适合各大CMS的主题模版开发参考&#xff0c;如常见的Wordpress主题开发、Z-Blo…

在python中解析命令行参数,并做一个命令行程序

命令行参数 加密程序 考虑这样一个加密程序&#xff0c;其中一个功能&#xff0c;是对一段字符串进行base64加密&#xff0c;另一个功能&#xff0c;是对一段base64字符串解密&#xff1a; import base64def encrypt_to_base64(input_string):byte_data input_string.encod…

ESP8266 自定义固件烧录-Tcpsocket固件

一、固件介绍 固件为自定义开发的一个适配物联网项目的开源固件&#xff0c;支持网页配网、支持网页tcpsocket服务器配置、支持串口波特率设置。 方便、快捷、稳定&#xff01; 二、烧录说明 固件及工具打包下载地址&#xff1a; https://download.csdn.net/download/flyai…

I.MX6U 裸机开发3. GPIO操作控制LED灯

I.MX6U 裸机开发3. GPIO操作控制LED灯 一、创建项目目录及源文件1. 新建目录2. 远程开发环境3. 创建源文件 二、代码编写1. 打开时钟2. 配置端口复用功能为GPIO3. 配置端口电气属性4. 设置GPIO方向&#xff08;GDIR寄存器&#xff09;5. 输出6. 死循环等待 三、编译程序1. 整体…

「Mac畅玩鸿蒙与硬件19」鸿蒙UI组件篇9 - 自定义动画实现

自定义动画让开发者可以设计更加个性化和复杂的动画效果&#xff0c;适合表现独特的界面元素。鸿蒙提供了丰富的工具&#xff0c;支持通过自定义路径和时间控制来创建复杂的动画运动。本篇将带你学习如何通过自定义动画实现更多样化的效果。 关键词 自定义动画动画路径贝塞尔曲…

FLUX 推出 Ultra 和 Raw 模式,仅10秒生成2K高清图!

大家好&#xff0c;我是渔夫。 就在 2024年11月6日&#xff0c;BlackForestLabs 团队升级了他们最新的文生图模型 FLUX1.1 [pro]。 推出 Ultra 和 Raw 模式&#xff0c;仅10秒就能生成2K高清图片&#xff0c;速度非常惊人。 Ultra 模式&#xff1a;可生成超高分辨率图像&#x…

24/11/6 算法笔记 SVD

SVD&#xff0c;即奇异值分解&#xff08;Singular Value Decomposition&#xff09;&#xff0c;是线性代数中一种重要的矩阵分解方法。 定义 对于任何给定的 mnmn 的实数矩阵 AA&#xff08;其中 mm 是行数&#xff0c;nn 是列数&#xff09;&#xff0c;SVD分解可以表示为…

开发笔记 | 快速上手基于Dify等第三方大模型平台接口实现AI智能聊天

前置&#xff1a; 1.部署Dify&#xff0c;见官方教程及介绍https://docs.dify.ai/zh-hans&#xff0c;本文主要讲基于部署完之后的java实现的调用它的接口实现AI智能聊天&#xff0c;其他AI功能后续有用到再补充&#xff0c;没有就看缘分 2.什么是Dify&#xff1f;可以简单理解…

数据分析:转录组差异fgsea富集分析

文章目录 介绍加载R包数据链接导入数据数据预处理DE testing: 2BP vs no-BP比较limma-voomLoad steroid dataIn No-BP patientsIn 2BP patientsCompare gene expression vs bacterial mass其他系统信息介绍 转录组差异fgsea富集分析是一种基于基因集的富集分析方法,它关注的是…

查看网路信息-ifconfig命令

1.ifconfig缺点&#xff1a; 可以查看接口的网络类型&#xff1b;部分IP和掩码以及状态是否插线&#xff0c;看不到接口下的网关&#xff0c;DNS, 要想看到接口下多个IP,使用 ip addr show 命令 要想看网关&#xff0c;使用 ip route show 命令、route -n 命令 显示路由表内…

基于Spring Boot的中小型制造企业质量管理系统设计与实现,LW+源码+讲解

摘 要 信息数据从传统到当代&#xff0c;是一直在变革当中&#xff0c;突如其来的互联网让传统的信息管理看到了革命性的曙光&#xff0c;因为传统信息管理从时效性&#xff0c;还是安全性&#xff0c;还是可操作性等各个方面来讲&#xff0c;遇到了互联网时代才发现能补上自…

Java:多态的调用

1.什么是多态 允许不同类的对象对同一消息做不同的响应。即同一消息可以根据发送对象的不同而采用多种不同的行为方式。&#xff08;发送消息就是函数调用&#xff09;。多态使用了一种动态绑定&#xff08;dynamic binding&#xff09;技术&#xff0c;指在执行期间判断所引用…

并查集算法详解

文章目录 并查集概念并查集的常见操作构建并查集合并并查集和查找 关于find函数 并查集概念 并查集&#xff08;Union-Find&#xff09;是一种树型的数据结构&#xff0c;用于处理一些不交集的合并及查询问题。其主要应用是判断两个元素是否在同一个集合中&#xff0c;以及合并…

Redis持久化机制——针对实习面试

目录 Redis持久化机制Redis为什么要有持久化机制&#xff1f;Redis持久化方式有哪些&#xff1f;AOF持久化工作原理是什么&#xff1f;有什么优缺点&#xff1f;AOF持久化工作原理AOF的优点AOF的缺点 RDB持久化工作原理是什么&#xff1f;有什么优缺点&#xff1f;RDB持久化工作…

【系统架构设计师(第2版)】七、系统架构设计基础知识

有效的软件体系结构及其明确的描述和设计&#xff0c;已成为软件工程领域中重要的主题。 *注&#xff1a;由于历史原因&#xff0c;研究者和工程人员对**Software Architecture&#xff08;简称SA&#xff09;*的翻译不尽相同&#xff0c;本文中软件“体系结构”和“架构”具有…