InMemoryUploadedFile を保存せず文字コード変換

タイトルの長さに反して、短いノウハウですが、
Django を使用し、Form から取得したファイルをローカルに保存することなく、
文字コード変換を行なって読み込む方法です。
処理速度が必要だとか、EC2 の micro インスタンスで容量を使いたくない時に便利。

HTML 側

HTML は単純にファイルを指定する欄と送信ボタンだけ。 csrf_token は Django で POST するなら必須。
そんな話を 書いてた。

<form action="/import" method="POST">
  {% csrf_token %}
  <input type="file" id="fileImport" name="fileImport" enctype="multipart/form-data">
  <input type="submit">
</form>

ちなみに、 Ajax 的にファイルをアップロードしたければ
jQuery.upload: A simple ajax file upload plugin が便利です。
jQuery.ajax() のように success と error で分岐出来ないので注意が必要ですが。

Python

view だけ。基本的に1行ずつ読み込んでエンコードを繰り返します。

def file_import(request, method=["GET", "POST"]):
  """ ファイル取得 """
  imported_file = request.FILES.get("fileImport")
  """ 1行読み込んで エンコード """
  dic_line = unicode(dic_file.readline(), "utf-8")
  while dic_line:
    """
    読み込み処理 何かする
    """
    """ 次の行へ """
    dic_line = unicode(dic_file.readline(), "utf-8")
  """
  何か Return する
  """

CSV ライブラリに読み込ませる

CSV ライブラリに直接食わせる事も可能ですが、
1行全部のエンコードは効かなくなるので、項目ごとにエンコードが必要になります。

import csv
csv_file = csv.reader(imported_file)
for row in csv_file:
  a = unicode(row[0], "utf-8")

まとめ

InMemoryUploadedFile の扱いが厄介で色々詰まったりしましたが、
基本的に open(file_path, "rb") したファイルと (ほぼ) 同等に扱えるという事に
気付いてからは応用範囲が広げられた気がします。


しかし、Pythonエンコードが絡むと一癖あるな…。


と、そんな感じで、最近 blog 書いてなかったですが、
相変わらずこういう小手先な事ばかりやってます…。
まぁ、小手先でもお役に立てれば幸い。