zoukankan      html  css  js  c++  java
  • 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)
    View Code

    主要方法: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
    View Code

    配置文件: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)
    View Code

    扫描二维码显示页面: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>
    View Code

    nginx转发配置,server内加入

            location /report {
                proxy_pass   http://127.0.0.1:9090/report;
            }
    View Code

    pdf转高清图片

    直接用ps转,高清大图

    https://jingyan.baidu.com/article/a3f121e4e08725fc9052bb00.html

  • 相关阅读:
    iOS取消按钮点击时的动画效果
    iOS实现简书和知乎的上滑隐藏导航栏下拉显示导航栏效果
    idea添加Jetty时提示JMX module is not included
    人的差别在于业余时间,而一个人的命运决定于晚上8点到10点之间
    如果做好一个出色的程序员
    阅读的技巧
    JQuery返回布尔值Is()方法.条件判断
    Javascript遍历each与map
    html5Canvas绘制弧线(圆形)
    jQuery插件背景滑动菜单(第二次自已偿试写插件)
  • 原文地址:https://www.cnblogs.com/lurenjia1994/p/10118489.html
Copyright © 2011-2022 走看看