Djangoでフォームで受け取った複数のファイルを、パスワード付きZIPで固めてmodelに保存したかった。
Pythonの標準モジュールzipfileではpass付きを展開はできても、作成はできないのでpyminizipを使う。
ファイル名と、中身を別々に渡せれば一時ファイルでもいいんだけど、pyminizipにはファイルパスのリストを渡す必要がある。
その際、一時ファイルを使ってしまうと、ファイル名がランダム文字列になってしまうので、フォームから送られてきたファイル名を維持するために一時ディレクトリを使い、その中にアップロードされた名前でファイルを作成する。
with文を使ってるので、closeとかの処理が省けるし、ブロックを抜けた時にすぐ消えてくれるので気持ちがいい。
コードは実コードをサンプル用に手を入れてるので動かなさそう。
views.py
import os
import pyminizip
from tempfile import TemporaryDirectory
from .models import ZipFile
def index(request):
if request.method == 'POST':
form = MailForm(request.POST, request.FILES)
if form.is_valid():
# djangoのフォームからファイル取り出す
received_files = request.FILES.getlist('file_field')
password = "pass"
temp_file_list = []
with TemporaryDirectory() as temp_dir:
# ZIPファイルの名前には最初のファイルの名前を拡張子zipにしてつかう
zip_path = os.path.join(temp_dir, os.path.splitext(received_files[0].name)[0] + '.zip')
for f in received_files:
# pyminizipに渡す時に一時ファイルのままだと、名前がランダムな感じで良くないので
# request.FILESから取り出すして使う
temp_path = os.path.join(temp_dir, f.name)
with open(temp_path, "wb") as tmp_f:
tmp_f.write(f.read())
temp_file_list.append(temp_path)
pyminizip.compress_multiple(temp_file_list,
zip_path,
password, 2)
temp_zip = File(open(zip_path, "rb"))
# djangoのmodel
zipfile = ZipFile()
# zip_pathのままにしてしまうと、/tmp/xxxの階層つきでZIPに入ってしまうのでファイル名だけ渡す
zipfile.file_field.save(os.path.basename(zip_path), temp_zip)
zipfile.save()- 作者: 淵上 喜弘
- 出版社/メーカー: 淵上 喜弘
- 発売日: 2016/12/04
- メディア: Kindle版
- この商品を含むブログを見る
- 作者: 露木誠
- 出版社/メーカー: 技術評論社
- 発売日: 2009/02/16
- メディア: 単行本(ソフトカバー)
- 購入: 10人 クリック: 129回
- この商品を含むブログ (36件) を見る
- 作者: 淵上 喜弘
- 発売日: 2017/05/10
- メディア: Kindle版
- この商品を含むブログを見る