CherryPyメモ

・ファイルのダウンロードについて。

from cherrypy.lib.cptools import *

@expose
def download(self):

    localDir = os.path.dirname(__file__)
    absDir = os.path.join(os.getcwd(), localDir)

    path = os.path.join(absDir, 'images.zip')

    zf = zipfile.ZipFile(path, mode='w')
    for i in self.session.query(ImageData).select():
        zf.writestr(str(i.image_id) + '_' + i.image_name,
                    base64.b64decode(i.image_data))
    else:
        zf.close()
    
    return serveFile(path,
                     contentType='application/x-download',
                     disposition='attachment',
                     name=os.path.basename(path))

かなり省略してます。

データベース内にある画像をzipファイルに固めて出力します。

参考文献というかパクリもと

CherryPy - a pythonic, object-oriented web development framework
http://www.cherrypy.org/file/trunk/cherrypy/tutorial/tut09_files.py

一時的にファイルをどこかにおいておかないとダメみたいですね。
もう少し単純にしてみたいです。

serveFileがややこしすぎます…。

追記:

上記のままだと複数ファイルを追加したい場合にエラー(UnicodeDecodeError
)がでます。

なにやらWindows特有の問題らしいです。

で、以下修正

from cherrypy.lib.cptools import *

@expose
def download(self):
    localDir = os.path.dirname(__file__)
    absDir = os.path.join(os.getcwd(), localDir)

    path = os.path.join(absDir, 'images.zip')

    zf = zipfile.ZipFile(path, mode='w')
    for i in self.session.query(ImageData).select():
        name = (str(i.image_id) + "_" + i.image_name).encode("utf-8")
        info = zipfile.ZipInfo(name)
        info.compress_type = zipfile.ZIP_DEFLATED
        zf.writestr(info, base64.b64decode(i.image_data))
    else:
        zf.close()
    
    return serveFile(path,
                     contentType='application/x-download',
                     disposition='attachment',
                     name=os.path.basename(path))

.encode("utf-8")を追加するのとZipInfoを正しく引数に与えてやると問題ないようです。

ずばりそのままの解決策が載っているサイト

Unicode and Zipfile problems - Python
http://www.thescripts.com/forum/thread24652.html

これで画像ファイルをzipファイルにしてダウンロードすることが出来るようになりました。