flask 文件转为pdf并添加二维码
背景:
宝安区需求,企业会下载表格,打印后填报。填报后收上表格,统一录入PDA。因为某台PDA只能录某个地方的表格,所以他们希望纸质表上有个二维码,扫描出现填报公司的一些信息,以及统计(好像是这样,没文档,口头说的)。
访问文件下载接口,传入user_id,就能下载到带有user_id二维码的问卷,扫描二维码,会出现一个信息页面,点击完成按钮,会将该公司状态更新为完成。
很小的项目,从头到尾简单纪录一下
整个项目
flask框架:main.py
import sys, time, os from util import * from flask import Flask, jsonify, g, make_response, send_from_directory, request, render_template from flask_cors import CORS reload(sys) sys.setdefaultencoding('utf8') app = Flask(__name__) app.app_context().push() @app.before_request def before_request(): pass @app.after_request def after_request(response): response.headers['Access-Control-Allow-Origin'] = '*'#处理跨域 return response @app.route('/report/down') def down(): user_id = request.args['user_id'] count(user_id, 'down') file_name = mergePdf(user_id) remove_file(file_name) return send_from_directory(os.getcwd(), file_name, as_attachment=True) @app.route('/report/complete') def complete(): user_id = request.args['user_id'] count(user_id, 'complete') return jsonify({}) @app.route('/report/detail') def detail(): info = reportInfo() info['noComplete'] = info['len']-info['down'] info['area_name'] = '西乡街道'#暂时写死 info['user_id'] = request.args['user_id'] return render_template("result.html", info=info) @app.route('/report/report_info') def report_info(): return jsonify(reportInfo()) def runFlask(port): app.run(host='0.0.0.0', port=port, threaded=True)#异步请求 CORS(app, supports_credentials=True) if '__main__' == __name__: runFlask(9090)
主要方法:util.py
生成pdf这块做得比较麻烦(有其他方法请跟我说)
画布生成pdf,先画表格图片,再画二维码图片
二维码是浮在原文件左上角,好像只能用画布的形式才能生成,而画布生成的pdf只有一页(就算设置了pageSize,打印的时候也只有一页),所以生成了多个pdf,最后再合并的
import qrcode, PyPDF2, codecs, os, time from threading import Thread from config import MRedis from reportlab.lib.pagesizes import letter, A4 from reportlab.lib.units import inch from reportlab.pdfgen import canvas def async(f): def wrapper(*args, **kwargs): thr = Thread(target = f, args = args, kwargs = kwargs) thr.start() return wrapper def count(user_id, status): MRedis.hset("reportCount", user_id, status) def reportInfo(): result = { 'down': 0, 'complete': 0 } obj_name = "reportCount" keys = MRedis.hkeys(obj_name) for i in keys: status = MRedis.hget(obj_name, i) result[status] = result[status]+1 result['len'] = len(keys) return result def getQRCode(user_id): qr=qrcode.QRCode(version = 2,error_correction = qrcode.constants.ERROR_CORRECT_L,box_size=10,) qr.add_data('http://服务器/report/detail?user_id='+user_id) # qr.add_data('http://10.0.0.17:9090/report/detail?user_id='+user_id) qr.make(fit=True) img = qr.make_image() img_name = getQRName(user_id) img.save(img_name) return img_name def getQRName(user_id): return user_id+'.png' def getPdfNameByName(user_id, name): return user_id +'_'+ name.split('.')[0]+'.pdf' def createPdf(user_id, name, path='base_imgs/'): width, height = A4 c = canvas.Canvas(getPdfNameByName(user_id, name), pagesize=A4) c.drawImage(path+name, 0, 0, height=height, width=width) c.drawImage(getQRCode(user_id), 0 , height-100, height=100, width=100) c.save() @async#10秒后删除文件 def remove_file(path): time.sleep(10) os.remove(path) def mergePdf(user_id): imgs = { 0: '611.jpg', 2: '611-1.jpg', 3: '611-2.jpg', 4: '611-3.jpg', 5: '611-4.jpg', 6: '611-5.jpg', 7: '611-6.jpg', 8: '612.jpg', } for idx in imgs: createPdf(user_id, imgs[idx]) pdfwriter = PyPDF2.PdfFileWriter() pdfreader = PyPDF2.PdfFileReader(open('base_imgs/base.pdf', "rb")) fs = {}#文件对象,等写入pdf完成,关闭所有文件流,以做删除 for page in range(pdfreader.numPages): if page in imgs: file_path = getPdfNameByName(user_id, imgs[page]) f = open(file_path, "rb") temp = PyPDF2.PdfFileReader(f) pdfwriter.addPage(temp.getPage(0)) fs[file_path] = f else: pdfwriter.addPage(pdfreader.getPage(page)) file_name = user_id + '_all.pdf' with codecs.open(file_name, 'wb') as f: pdfwriter.write(f) os.remove(getQRName(user_id))#删除二维码 for path in fs: fs[path].close()#关闭流 os.remove(path)#删除文件 return file_name
配置文件:config.py
使用redis中set保存问卷下载状态,某企业下载,往reportCount添加key,key的值分别为down, complete
import redis pool = redis.ConnectionPool(host='127.0.0.1', port=6379) MRedis = redis.Redis(connection_pool=pool)
扫描二维码显示页面:templates/result.html
点击按钮,将状态更新为完成
<!DOCTYPE html> <html> <head> <title>你的信息</title> <script src="https://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script> </head> <body> <table> <h1>你的信息</h1> <h3>法人码:{{info.user_id}}</h3> <h3>所属区域:{{info.area_name}}</h3> <h1>问卷信息</h1> <h3>已下载:{{info.down}}</h3> <h3>已完成:{{info.complete}}</h3> <h3>未完成:{{info.noComplete}}</h3> <button id="completeBtn">已完成问卷上传请点这里</button> </table> <script> function getUrlParam (name){ var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)") var r = window.location.search.substr(1).match(reg) if (r !== null) return unescape(r[2]) return null } $(document).ready(function(){ $('#completeBtn').click(function(){ $.ajax({ url: 'http://服务器/report/complete?user_id='+getUrlParam('user_id'), success: function(obj){ alert('您的问卷状态已更新为完成!') location.reload() } }) }) }) </script> </body> </html>
nginx转发配置,server内加入
location /report { proxy_pass http://127.0.0.1:9090/report; }
pdf转高清图片
直接用ps转,高清大图
https://jingyan.baidu.com/article/a3f121e4e08725fc9052bb00.html
Become a Linux Programmer