| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302 |
- #!/usr/bin/python
- # -*- coding: utf-8 -*-
- import cgi
- import os
- import datetime
- import uuid
- import json
- import zipfile
- # pip install requests
- import requests
- # pip install retry
- from retry import retry
- from http.server import BaseHTTPRequestHandler, HTTPServer
- '''
- 脚本运行说明:
- screen -S uploadServer
- nohup python3 ./server.py >/dev/null 2>&1 &
- 注意print有输出缓冲,使用-u参数,使得python不启用缓冲,这样就可以同步看到输出结果了。python -u ./server.py
- 关闭终端后再进入可以这样:
- screen -list
- 找到相关的screen id
- screen -r screenId
- '''
- def get_date_path():
- date_path = datetime.datetime.now().strftime("%Y/%m%d")
- return date_path
- def get_uuid_file():
- uuid_str = str(uuid.uuid1()).replace('-', '')
- return uuid_str
- def get_file_ext(path):
- return os.path.splitext(path)[1]
- DEBUG_MODE = True
- FILE_PATH = '/Volumes/HDD/workshop/old/ar.upload.ming/files'
- BASE_URL = 'http://ar.upload.ming/files' # 必须与商城common/config/params.php中的remoteUploadUrl一致
- # FILE_PATH = '/data/wwwroot/upload/files/'
- # BASE_URL = 'http://upload.ar.wqcms.com/files/'
- # 重试的次数
- RETRY_TIMES = 5
- # 重试的时间间隔,成倍增长
- RETRY_BACK_OFF = 2
- # 重试的间隔
- RETRY_DELAY = 2
- @retry(FileNotFoundError, tries=RETRY_TIMES, backoff=RETRY_BACK_OFF, delay=RETRY_DELAY)
- def notify_api(attachment_notify_url, data):
- res = requests.post(attachment_notify_url, data=data)
- if res.status_code == 200:
- notify_json = res.json()['message']
- return notify_json
- else:
- print(res)
- raise FileNotFoundError('文件上传失败')
- class UploadServer(BaseHTTPRequestHandler):
- cgi_form = None
- post_uid = None
- post_token = None
- post_date = None
- post_notify_url = None
- def output(self, data, code):
- self.send_response(code)
- self.send_header('Content-Type', 'application/json')
- self.end_headers()
- self.wfile.write(json.dumps(data).encode())
- def error(self, data, debug_info=None):
- if DEBUG_MODE and debug_info is not None:
- data += '[%s]' % (debug_info,)
- self.output(data, 400)
- def success(self, data, debug_info=None):
- if DEBUG_MODE and debug_info is not None:
- data += '[%s]' % (debug_info,)
- self.output(data, 200)
- @staticmethod
- def logger(msg):
- if not DEBUG_MODE:
- return False
- if isinstance(msg, tuple):
- msg = tuple(msg).__str__()
- elif isinstance(msg, list):
- msg = "".join(list(msg))
- elif isinstance(msg, dict):
- msg = json.dumps(msg)
- date_file = datetime.datetime.now().strftime("%Y%m%d") + '.log'
- log_file_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'logs')
- if not os.path.exists(log_file_path):
- os.makedirs(log_file_path)
- file = os.path.join(log_file_path, date_file)
- if not msg:
- msg = ''
- with open(file, 'a+') as f:
- date_time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
- msg = '[%s]%s' % (date_time, msg)
- f.write(msg + '\n')
- def request_logger(self, action, params):
- log_msg = '[%s]UID:%s,TOKEN:%s,DATE:%s,NOTIFY_URL:%s,PARAMS:%s' % (
- action, self.post_uid, self.post_token, self.post_date, self.post_notify_url, params,)
- self.logger(log_msg)
- def request_end_logger(self, action, data):
- log_msg = '[%s complete]UID:%s,TOKEN:%s,DATE:%s,NOTIFY_URL:%s,RESPONSE:%s' % (
- action, self.post_uid, self.post_token, self.post_date, self.post_notify_url, data,)
- self.logger(log_msg)
- def on_remove_file(self):
- local_file_path = self.cgi_form.getvalue('post_data')
- local_file_path = self.trim_base_url(local_file_path)
- # 记录请求日志
- self.request_logger('remove_file', local_file_path)
- target_path = os.path.join(FILE_PATH, local_file_path)
- file_exists = os.path.exists(target_path)
- success_data = {
- 'code': 200,
- 'error': 0,
- 'message': 'success',
- 'success': 1,
- }
- if not file_exists:
- success_data['message'] = target_path + ' file not exists'
- self.success(success_data)
- self.request_end_logger('remove_file', success_data)
- return
- try:
- # 删除文件
- os.remove(target_path)
- self.success(success_data)
- self.request_end_logger('remove_file', success_data)
- except BaseException as e:
- self.logger(e.args)
- self.error('文件删除失败', e.args[1])
- return
- @staticmethod
- def trim_base_url(str):
- return str.replace(BASE_URL + '/', '')
- def on_upload_file(self):
- # 临时文件路径
- attachment_file_path = self.cgi_form.getvalue('ATTACHMENT_path')
- # 原文件名
- attachment_file_name = self.cgi_form.getvalue('ATTACHMENT_name')
- # 文件大小
- attachment_file_size = self.cgi_form.getvalue('ATTACHMENT_size')
- # 文件md5
- attachment_file_md5 = self.cgi_form.getvalue('ATTACHMENT_md5')
- # 记录请求日志
- self.request_logger('upload', attachment_file_name)
- # 获取文件扩展名
- file_ext = get_file_ext(attachment_file_name)
- if not file_ext:
- file_ext = '.jpg'
- tmp_file_exists = os.path.exists(attachment_file_path)
- if not tmp_file_exists:
- self.error(404)
- return
- # 获取时间路径
- date_path = get_date_path()
- post_file_name = self.cgi_form.getvalue('file_name')
- if post_file_name:
- rnd_file = post_file_name
- else:
- # 获取随机文件名
- rnd_file = get_uuid_file() + str(file_ext)
- target_path = os.path.join(FILE_PATH, date_path)
- # 先判断文件夹是否存在,不存在就创建
- is_exists = os.path.exists(target_path)
- if not is_exists:
- os.makedirs(target_path)
- target_file = os.path.join(target_path, rnd_file)
- try:
- # 移动文件
- os.rename(attachment_file_path, target_file)
- # 生成URL
- file_url = target_file.replace(FILE_PATH, BASE_URL)
- data = {
- 'url': file_url,
- 'size': attachment_file_size,
- 'name': attachment_file_name,
- 'md5': attachment_file_md5,
- 'uid': self.post_uid,
- 'token': self.post_token,
- 'request_date': self.post_date,
- 'success': 1,
- }
- if self.post_notify_url:
- notify_result = notify_api(self.post_notify_url, data)
- data['IS_IMAGE'] = notify_result['IS_IMAGE']
- data['REMOTE_URL'] = notify_result['REMOTE_URL']
- data['url'] = notify_result['REMOTE_URL']
- self.success(data)
- self.request_end_logger('upload', data)
- except BaseException as e:
- self.logger(e.args)
- self.error('文件上传失败', e.args[0])
- return
- def on_zip_file(self):
- get_zip_files = self.cgi_form.getvalue('post_data')
- # 记录请求日志
- self.request_logger('zip_file', get_zip_files)
- zip_array = get_zip_files.strip(',').split(',')
- rnd_file = get_uuid_file() + '.zip'
- # 获取时间路径
- date_path = get_date_path()
- target_path = os.path.join(FILE_PATH, date_path)
- if not os.path.exists(target_path):
- os.makedirs(target_path)
- target_file = os.path.join(target_path, rnd_file)
- try:
- zip_file = zipfile.ZipFile(target_file, 'w', zipfile.ZIP_DEFLATED)
- for zf in zip_array:
- if not zf:
- continue
- zf = self.trim_base_url(zf)
- real_file = os.path.join(FILE_PATH, zf)
- is_exists = os.path.exists(real_file)
- if not is_exists:
- continue
- basename = os.path.basename(zf)
- zip_file.write(real_file, basename)
- # 生成URL
- file_url = target_file.replace(FILE_PATH, BASE_URL)
- data = {
- 'REMOTE_URL': file_url,
- 'success': 1,
- 'uid': self.post_uid,
- 'token': self.post_token,
- 'request_date': self.post_date,
- }
- if self.post_notify_url:
- notify_api(self.post_notify_url, data)
- self.success(data)
- self.request_end_logger('zip_file', data)
- except BaseException as e:
- self.logger(e.args)
- self.error('文件压缩失败', e.args[1])
- return
- def do_POST(self):
- self.cgi_form = cgi.FieldStorage(
- fp=self.rfile,
- headers=self.headers,
- environ={'REQUEST_METHOD': 'POST',
- 'CONTENT_TYPE': self.headers['Content-Type'],
- })
- action = self.cgi_form.getvalue('action')
- if not action:
- action = 'upload'
- # UID
- self.post_uid = self.get_params('UPLOAD-SERVER-USER')
- # TOKEN
- self.post_token = self.get_params('UPLOAD-SERVER-TOKEN')
- # REQUEST DATE
- self.post_date = self.get_params('UPLOAD-SERVER-DATE')
- # REQUEST NOTIFY URL
- self.post_notify_url = self.get_params('UPLOAD-SERVER-NOTIFY-URL')
- if 'upload' == action:
- self.on_upload_file()
- elif 'delete' == action:
- self.on_remove_file()
- elif 'download_zip' == action:
- self.on_zip_file()
- def get_params(self, key):
- if key in self.headers:
- return self.headers[key]
- return self.cgi_form.getvalue(key)
- httpd = HTTPServer(('127.0.0.1', 8000), UploadServer)
- print("Server started on 127.0.0.1,port 8000.....")
- httpd.serve_forever()
|