# -*- coding: utf-8 -*- import errno import glob # import logging import os import sqlite3 from functools import wraps from tornado.httpserver import HTTPServer from tornado.ioloop import IOLoop from tornado.log import app_log as logger from tornado.options import define, options from tornado.web import Application, RequestHandler, StaticFileHandler # logger = logging.getLogger('minipai2') # logger.addHandler(logging.StreamHandler()) # logger.setLevel(logging.INFO) # logger.propagate = False define('host', default='127.0.0.1', help='run on the given host', type=str) define('port', default=8001, help='run on the given port', type=int) options.parse_command_line() ROOT_PATH = '/home/work/minipai2' # Create Table SQL CREATE_TABLE_STMT = """ CREATE TABLE IF NOT EXISTS photoinfo ( id integer primary key, lensman varchar(20), session varchar(20), photo_id varchar(13), photo_name varchar(255), thumb_path varchar(255), origin_path varchar(255) );""" # Create Index SQL CREATE_INDEX1 = 'CREATE INDEX IF NOT EXISTS idx_lensman ON photoinfo (lensman);' CREATE_INDEX2 = 'CREATE INDEX IF NOT EXISTS idx_session ON photoinfo (session);' # Insert Record SQL INSERT_RECORD_STMT = 'INSERT INTO photoinfo VALUES (NULL, ?, ?, ?, ?, ?, ?);' # Delete Record SQL DELETE_RECORD_STMT = 'DELETE FROM photoinfo WHERE lensman = ? and session = ? and name = ?;' # Query Max(photo_id) SQL SELECT_MAX_PHOTO_ID_STMT = 'SELECT MAX(photo_id) FROM photoinfo WHERE lensman = ? and session = ?;' # Query Origin Path SQL SELECT_ORIGIN_PATH_STMT = 'SELECT origin_path FROM photoinfo WHERE lensman = ? and photo_id = ?;' conn = sqlite3.connect('minipai2.db') cur = conn.cursor() # Execute SQL cur.execute(CREATE_TABLE_STMT) cur.execute(CREATE_INDEX1) cur.execute(CREATE_INDEX2) conn.commit() # Logging Some Vars def logit(self, content, key='content'): uri = self.request.uri if hasattr(self, 'request') else self logger.info('uri=%s&%s=%s', uri, key, content) # Logging Request Arguments def log_request_arguments(func): @wraps(func) def returned_wrapper(self, *args, **kwargs): logit(self, self.request.arguments, key='arguments') return func(self, *args, **kwargs) return returned_wrapper # FILE OPERATE def silent_makdirs(path): try: os.makedirs(path) except OSError as e: if e.errno != errno.EEXIST: raise def silent_remove(path): try: os.remove(path) except OSError as e: if e.errno != errno.ENOENT: raise def get_session_root(lensman, session): return '{}/{}'.format(ROOT_PATH, session) def get_session_dir(lensman, session): session_root = get_session_root(lensman, session) return '{}/{}'.format(session_root, 'origin'), '{}/{}'.format(session_root, 'thumbnail') def create_session_dir(lensman, session): for path in get_session_dir(lensman, session): if os.path.exists(path): return False silent_makdirs(path) return True def get_last_timestamp(lensman, session): cur.execute(SELECT_MAX_PHOTO_ID_STMT, (lensman, session)) result = cur.fetchall() return int(result[0][0] or 0) def insert_session_file(lensman, session, id, name, thumb, origin): cur.execute(INSERT_RECORD_STMT, (lensman, session, id, name, thumb, origin)) conn.commit() def delete_session_file(lensman, session, name): cur.execute(DELETE_RECORD_STMT, (lensman, session, name)) conn.commit() def get_new_files(lensman, session, maxt): _, thumb = get_session_dir(lensman, session) files = glob.iglob('{}/*'.format(thumb)) news = [] for file_ in files: logit('/fetch_thumbnail', file_, key='globfile') if not file_.endswith('.tmp'): # Whether 'xxx.tmp' or not photo_name = file_.split('/')[-1] photo_id = photo_name.split('.')[0] thumb_path = file_.strip(ROOT_PATH) origin_path = thumb_path.replace('thumbnail', 'origin') if int(photo_id) > maxt: insert_session_file(lensman, session, photo_id, photo_name, thumb_path, origin_path) news.append({ 'id': photo_id, 'name': photo_name, 'path': thumb_path, }) return news def get_origin_path_from_id(lensman, session, id_): cur.execute(SELECT_ORIGIN_PATH_STMT, (lensman, id_)) result = cur.fetchall() if not result: return '' origin_path = result[0][0] if not os.path.isfile('{}/{}'.format(ROOT_PATH, origin_path)): return '' return origin_path class HelloHandler(RequestHandler): def get(self): self.write('Hello Tornado') class SessionStartHandler(RequestHandler): @log_request_arguments def post(self): lensman = self.get_argument('lensman', '') session = self.get_argument('session', '') # Create Session Dir created = create_session_dir(lensman, session) # Change Mode to 0777 os.chmod(get_session_root(lensman, session), 0777) self.write({ 'status': 200, 'data': { 'created': created, } }) class SessionEndHandler(RequestHandler): @log_request_arguments def post(self): lensman = self.get_argument('lensman', '') session = self.get_argument('session', '') # Change Mode to 0700 os.chmod(get_session_root(lensman, session), 0700) self.write({ 'status': 200, }) class FetchThumbnailHandler(RequestHandler): @log_request_arguments def post(self): lensman = self.get_argument('lensman', '') session = self.get_argument('session', '') maxt = get_last_timestamp(lensman, session) files = get_new_files(lensman, session, maxt) logit(self, maxt, key='maxt') logit(self, files, key='files') self.write({ 'status': 200, 'data': { 'files': files, } }) class FetchOriginHandler(RequestHandler): @log_request_arguments def post(self): lensman = self.get_argument('lensman', '') session = self.get_argument('session', '') id_ = self.get_argument('id', '') path = get_origin_path_from_id(lensman, session, id_) self.write({ 'status': 200, 'data': { 'path': path, } }) class DeletePhotoHandler(RequestHandler): @log_request_arguments def post(self): lensman = self.get_argument('lensman', '') session = self.get_argument('session', '') id_ = self.get_argument('id', '') name = self.get_argument('name', '') path = self.get_argument('path', '') # Delete Record from Sqlite3 delete_session_file(lensman, session, id_) # Delete Photo from Disk origin, thumb = get_session_dir(lensman, session) # Delete Thumbnail silent_remove('{}/{}'.format(thumb, name)) # Delete Origin silent_remove('{}/{}'.format(origin, name)) self.write({ 'status': 200, }) class BoxInfoHandler(RequestHandler): def post(self): self.write({ 'status': 200, 'data': { 'no.': 'paiai000001', 'status': { 'code': '200', 'msg': u'正常', } } }) handlers = [ (r'/', HelloHandler), (r'/session_start', SessionStartHandler), (r'/session_end', SessionEndHandler), (r'/fetch_thumbnail', FetchThumbnailHandler), (r'/fetch_origin', FetchOriginHandler), (r'/delete_photo', DeletePhotoHandler), (r'/box_info', BoxInfoHandler), (r'/static/(.*)', StaticFileHandler, {'path': ROOT_PATH}), ] def main(): app = Application(handlers=handlers, default_host=options.host) server = HTTPServer(app) server.listen(options.port) IOLoop.current().start() if __name__ == '__main__': main()