LoginSignup
0
0

More than 5 years have passed since last update.

Heroku の Flask で PDF,XLSX,ZIP を作成

Last updated at Posted at 2018-11-02

JSON をアップロードして、PDF,XLSX,ZIP を作成します。

フォルダーの構造

.
├── json_upload.py
├── json_read.py
├── dict_to_pdf.py
├── dict_to_xlsx.py
├── zip_gen.py
├── Procfile
├── requirements.txt
└── static
    ├── data
    └── upload.html
json_upload.py
# -*- coding: utf-8 -*-
#
#   json_upload.py
#
#                  Nov/02/2018
#
# ------------------------------------------------------------------
from flask import Flask, request, make_response, jsonify
import os
import sys
import werkzeug

from json_read import json_read_proc
# ------------------------------------------------------------------
# flask
app = Flask(__name__)

# limit upload file size : 1MB
app.config['MAX_CONTENT_LENGTH'] = 1 * 1024 * 1024
#
#
UPLOAD_DIR="./static/data"

# ------------------------------------------------------------------
@app.route('/')
def welcome():
    return app.send_static_file('upload.html')
# ------------------------------------------------------------------
@app.route('/hello')
def hello():
    str_out = "<h2>"
    str_out += "皆さん、こんにちは<p />"
    str_out += "</h2>"
    str_out += "Nov/02/2018 PM 16:23<p />"
    return str_out

# ------------------------------------------------------------------
@app.route('/upload', methods=['POST'])
def upload_multipart():
    str_out = ""
    sys.stderr.write("*** upload_multipart *** start ***\n")
    if 'uploadFile' not in request.files:
        make_response(jsonify({'result':'uploadFile is required.'}))
#
    upload_files = request.files.getlist('uploadFile_aa')
    sys.stderr.write("len(upload_files) = %d\n" % len(upload_files))
    for file in upload_files:
        fileName = file.filename
        sys.stderr.write("fileName = " + fileName + "\n")
        file_path = os.path.join(UPLOAD_DIR, fileName)
        file.save(file_path)
        try:
            str_out += json_read_proc(UPLOAD_DIR, fileName)
        except Exception as ee:
            sys.stderr.write("*** error *** in json_read_proc ***\n")
            sys.stderr.write(str(ee) + "\n")
#
    sys.stderr.write("*** upload_multipart *** end ***\n")
#
    return str_out
#
# ------------------------------------------------------------------
@app.errorhandler(werkzeug.exceptions.RequestEntityTooLarge)
def handle_over_max_file_size(error):
    print("werkzeug.exceptions.RequestEntityTooLarge")
    return 'result : file size is overed.'

# ------------------------------------------------------------------
# main
if __name__ == "__main__":
    print(app.url_map)
    app.run(host='0.0.0.0', port=3000)
#
# ------------------------------------------------------------------
json_read.py
# -*- coding: utf-8 -*-
#
#   json_read.py
#
#                     Nov/02/2018
#
# ------------------------------------------------------------------
import os
import sys
import json
#
from dict_to_pdf import dict_to_pdf_proc
from dict_to_xlsx import dict_to_xlsx_proc
from zip_gen import zip_gen_proc
# ------------------------------------------------------------------
# [6]:
def json_read_proc(upload_dir,file_json):
#
    str_out = ""
    path_json = os.path.join(upload_dir,file_json)
#
    json_str = file_to_str_proc(path_json)
    dict_aa = json.loads(json_str)
    try:
        str_out = table_gen_proc(dict_aa)
    except Exception as ee:
        sys.stderr.write("*** error *** read_line_proc ***\n")
        sys.stderr.write(str (ee))
#
    file_pdf = file_json.replace("json","pdf")
    path_pdf = os.path.join(upload_dir,file_pdf)
    try:
        dict_to_pdf_proc(path_pdf,dict_aa)
    except Exception as ee:
        sys.stderr.write("*** error *** dict_to_pdf_proc ***\n")
        sys.stderr.write(str (ee))
#
    file_xlsx = file_json.replace("json","xlsx")
    path_xlsx = os.path.join(upload_dir,file_xlsx)
#
    try:
        dict_to_xlsx_proc(path_xlsx,dict_aa)
    except Exception as ee:
        sys.stderr.write("*** error *** dict_to_xlsx_proc ***\n")
        sys.stderr.write(str (ee))
#
    file_zip = file_json.replace("json","zip")
    path_zip = os.path.join(upload_dir,file_zip)
    try:
        zip_gen_proc(upload_dir,file_zip,file_json,file_pdf,file_xlsx)
    except Exception as ee:
        sys.stderr.write("*** error *** zip_gen_proc ***\n")
        sys.stderr.write(str (ee))
#
    str_out += "<blockquote>"
    str_out += '<a href="' + path_pdf + '">' + file_pdf + '</a><p />'
    str_out += '<a href="' + path_xlsx + '">' + file_xlsx + '</a><p />'
    str_out += '<a href="' + path_zip + '">' + file_zip + '</a><p />'
    str_out += "</blockquote>"
#
    return  str_out
#
# ------------------------------------------------------------------
# [6-2]:
def file_to_str_proc(file_in):
    str_out = ""
    try:
        fp_in = open(file_in,encoding='utf-8')
        str_out = fp_in.read()
        fp_in.close()
    except Exception as ee:
        sys.stderr.write("*** error *** file_to_str_proc ***\n")
        sys.stderr.write(str (ee))
#
    return  str_out
# ------------------------------------------------------------------
# [6-4]:
def table_gen_proc(dict_aa):
    str_out = ""
    str_out += "<table border=1px>"
    count = 0
    for key in dict_aa.keys():
        str_out += "<tr>"
        str_out += "<td>%d</td>" % count
        str_out += "<td>" + key + "<td />"
#
        unit_aa =  dict_aa[key]
        for col in unit_aa.values():
            str_out += "<td>" + str(col) + "<td />"
        str_out += "</tr>"
#
        count += 1
#
    str_out += "</table>"
#
    return  str_out
# ------------------------------------------------------------------
dict_to_pdf.py
# ------------------------------------------------------------------
#
#   dict_to_pdf.py
#
#                       Nov/02/2018
# ------------------------------------------------------------------
import os
import sys
#
from reportlab.pdfbase.cidfonts import UnicodeCIDFont
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfgen import canvas
# ------------------------------------------------------------------
def dict_to_pdf_proc(file_pdf,dict_aa):
    from reportlab.pdfgen import canvas
    fontname_g = "HeiseiKakuGo-W5"
    pdfmetrics.registerFont(UnicodeCIDFont (fontname_g))
    canvas = canvas.Canvas(file_pdf)

    canvas.setFont(fontname_g, 20)

    ypos = 700
    for key in sorted(dict_aa.keys()):
        unit = dict_aa[key]
        canvas.drawString(50,ypos,key)
        canvas.drawString(185,ypos,unit['name'])
        canvas.drawString(285,ypos,str (unit['population']))
        canvas.drawString(400,ypos,unit['date_mod'])
        ypos = ypos - 25
#
    canvas.save()
# ------------------------------------------------------------------
dict_to_xlsx.py
# ------------------------------------------------------------------
#
#   dict_to_xlsx.py
#
#                   Nov/02/2018
# ------------------------------------------------------------------
import sys
#
from openpyxl import Workbook
# ------------------------------------------------------------------
def dict_to_xlsx_proc (xlsx_file,dict_aa):
    wb = Workbook()
    ws = wb.worksheets[0]
    ws.title = "Cities"
    print ("ws.max_row = %d" % ws.max_row)
#
    keys_list = list(dict_aa.keys())
    print ("len = %d\n" % len(keys_list)) 
#
    for it in range (len(keys_list)):
        jt = it + 1
        key = keys_list[it]
        unit_aa = dict_aa[key]
#
        ws['A%d' % jt] = key
        ws['B%d' % jt] = unit_aa['name']
        ws['C%d' % jt] = unit_aa['population']
        ws['D%d' % jt] = unit_aa['date_mod']
#
    wb.save (filename = xlsx_file)
    wb.close()
#
# ------------------------------------------------------------------
zip_gen.py
# -*- coding: utf-8 -*-
#
#   zip_gen.py
#
#                      Nov/02/2018
#
# ------------------------------------------------------------------
import os
import sys
#
import zipfile
#
# ------------------------------------------------------------------
def zip_gen_proc(upload_dir,file_zip,file_json,file_pdf,file_xlsx):
#
    path_zip = os.path.join(upload_dir,file_zip)
    path_json = os.path.join(upload_dir,file_json)
    path_pdf = os.path.join(upload_dir,file_pdf)
    path_xlsx = os.path.join(upload_dir,file_xlsx)
#
    try:
        wzip = zipfile.ZipFile(path_zip,mode='w')
        wzip.write(path_json,file_json)
        wzip.write(path_pdf,file_pdf)
        wzip.write(path_xlsx,file_xlsx)
        wzip.close()
    except Exception as ee:
        sys.stderr.write("*** error *** in zipfile ***\n")
        sys.stderr.write(str(ee) + "\n")
#
# ------------------------------------------------------------------
Procfile
web: gunicorn json_upload:app --log-file -
requirements.txt
Flask==1.0.2
gunicorn==19.9.0
reportlab==3.5.9
pdfrw==0.4
openpyxl==2.5.9
static/upload.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta http-equiv="CONTENT-TYPE" content="text/html; charset=utf-8" />
<title>JSON Upload</title>
</head>
<body>
<h2>JSON 変換システム</h2>
<form action="/upload" method="post" enctype="multipart/form-data"> 
    <input type="file" name="uploadFile_aa"/ multiple="multiple">
    <input type="submit" value="submit"/>
</form>
<p />
<blockquote>
json をアップロードして下さい。<p />
PDF, xlsx, zip が作成されます。<p />
</blockquote>
<p />
Nov/02/2018 PM 16:36<p />
</body>
</html>

ビルトインサーバーでのテスト

python json_upload.py

heroku_nov0201.png

uWSGI でのテスト

uwsgi --plugin http,python --http :9090 \
    --wsgi-file json_upload.py --callable app

heroku_nov0202.png

テストに使う JSON

cities.json
{
  "t0921": {
    "name": "宇都宮",
    "population": 41295,
    "date_mod": "2003-8-12"
  },
  "t0922": {
    "name": "小山",
    "population": 38756,
    "date_mod": "2003-5-15"
  },
  "t0923": {
    "name": "佐野",
    "population": 71294,
    "date_mod": "2003-6-8"
  },
  "t0924": {
    "name": "足利",
    "population": 27138,
    "date_mod": "2003-7-21"
  },
  "t0925": {
    "name": "日光",
    "population": 74682,
    "date_mod": "2003-4-19"
  },
  "t0926": {
    "name": "下野",
    "population": 82951,
    "date_mod": "2003-10-14"
  }
}

Heroku へのアップロード方法
Heroku で Flask を使う

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0