画像アップロード

CherryPy + SQLAlchemy + SQLite

で、作成いたしました。
Ajaxなんて高度なものには対応しておりませぬ。
画像に対するバリデーションも出来てません。

以下スクリーンショット
f:id:Voluntas:20060711230039p:image

テストに使用している画像は
下記の友人のBlogからで、
使用許可を頂いております。

どことなくなんとなく
http://dokotonaku.jugem.jp/

以下プログラム

#Python 2.4.3
import base64
import random
import string
#CherryPy 2.2.1
import cherrypy
#SQLAlchemy 0.2.5
from sqlalchemy import *
#ElementTree 1.2.6
from elementtree.ElementTree import *

class File(object):
    def __init__(self, name, type, data, comment=""):
        self.L = list(string.ascii_letters + '0123456789')
        
        self.file_id = None
        self.name = name
        self.comment = comment
        self.type = type
        self.address = self._getRandomAscii()
        self.data = data
        
    def _getRandomAscii(self):
        key = ""
        for i in range(32):
            key += random.choice(self.L)
        return key

class Root(object):
    
    def __init__(self):
        sqlite_db = create_engine('sqlite:///upload1.db')
        metadata = BoundMetaData(sqlite_db)
        
        self.files_table = Table('files', metadata,
                             Column('file_id', Integer, primary_key = True),
                             Column('name', String),
                             Column('comment', String),
                             Column('type', String),
                             Column('address', String),
                             Column('data', Binary)
                            )
        metadata.create_all()
        
        mapper(File, self.files_table, properties = {
            'data': deferred(self.files_table.c.data)
        })
        
        self.session = create_session()
        
    def _viewImage(self):
        L = self.session.query(File).select()
        P = Element('p')

        if len(L) != 0:
            for i in L:
                IMG = Element('img', {'src': 'image/' + i.address,
                                      'alt': i.name,
                                      'width': '200'})
                P.append(IMG)
        
        return tostring(P)
    
    def index(self):
        return """
        <html><body>
            <form action="upload" method="post" enctype="multipart/form-data">
            filename: <input type="file" name="myFile"/><br/>
            <input type="submit"/>
            </form><br/>
            %s
        </body></html>
        """ % (self._viewImage())
    index.exposed = True
    
    def upload(self, myFile):

        self.session.save(File(
            name=myFile.filename,
            type=myFile.type,
            data=base64.b64encode(myFile.value),
            ))
        self.session.flush()

        return """
        <html><body>
            myFile filename: %s<br/>
            myFile mime-type: %s<br/>
            The file has been saved.<br/>
            %s
        </body></html>
        """ % (
            myFile.filename,
            myFile.type,
            self._viewImage()
        )
    upload.exposed = True
    
    def image(self, address):
        r = self.session.query(File).select_by(
            self.files_table.c.address==address)
        return base64.b64decode(r[0].data)
    image.exposed = True

cherrypy.root = Root()
cherrypy.server.start()

もっと効率よく書きたいものです。
かぎりなくユニークなアドレスを作成するためちょろっとしたプログラム書いていますが、
実はこれが意外にお気に入りです。

自分への課題
・画像の追加をMochiKitを使ってナイスでグッドな感じにする。
・HTMLを直接書くのではなくKidを使ってみる。

つまり出来る限りTurboGearsに近づける。