bottle + pythonでCSVファイルをアップロードした時にはまった時のメモです。
index.pyを下記の用に実装しました。
CSVをアップロードしてサーバ上には保存せずバイトデータを文字列に変換して画面に表示。
最終的にCSVはexcelで保存したファイルをアップロードします。
サンプルプログラム1
index.py
from bottle import post, get, run, request, response,template @get('/upload/<name>') def upload_page(name): return template("view/upload/upd_" + name + ".html") @post('/upload/<name>') def upload(name): res = {} data = request.files.data if data and data.file: # ファイル読み込み data = data.file.read() # 文字列型にデコード data = data.decode() res["str"] = data return template("view/upload/upd_" + name + "_result.html", res=res)
アップロード用html
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <title>アップロード</title> </head> <body> <h1>アップロード</h1> <form action="upload/dividend" method="post" enctype="multipart/form-data"> ファイル:<input type="file" name="data"/> <input type="submit" value="アップロード" /> </form> </body> </html>
アップロード結果用html
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <title>アップロード結果</title> </head> <body> <h1>アップロード結果</h1> {{res["str"]}} </body> </html>
テスト用CSV
cd,value 001,データ1 002,データ2
アップロード結果
読み込んだCSVファイルの中身が表示されました。
サンプルプログラム2
CSVデータを操作しやすいように標準ライブラリのcsv.DictReaderを使用するように変更しました。
index.py
import io import csv from bottle import post, get, run, request, response,template @get('/upload/<name>') def upload_page(name): return template("view/upload/" + name + ".html") @post('/upload/<name>') def upload(name): res = {} data = request.files.data if data and data.file: # ファイル読み込み data = data.file.read() # 文字列型にデコード data = data.decode() # 文字列をファイルとして扱う strio = io.StringIO(data) # csvをDict型で読み込む data = csv.DictReader(strio) res["csv"] = data return template("view/upload/" + name + "_result.html", res=res)
アップロード結果用html
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <title>アップロード結果</title> </head> <body> <h1>アップロード結果</h1> %for dt in res["csv"]: {{dt}} %end </body> </html>
サンプルプログラム3
BOMに対応するためdecode部分を変更しました。
# 文字列型にデコード data = data.decode("utf-8-sig")
アップロード結果
無事に\ufeffが表示されなくなりました。