初始化项目
This commit is contained in:
@@ -0,0 +1,197 @@
|
||||
"""
|
||||
数字城管文件上传。
|
||||
"""
|
||||
import asyncio
|
||||
import datetime
|
||||
import io
|
||||
import json
|
||||
import logging
|
||||
from typing import Optional
|
||||
|
||||
from tornado.httpclient import HTTPResponse, HTTPRequest
|
||||
|
||||
import dock
|
||||
from dock.dcm import dcm_api
|
||||
from dock.oa import PushException
|
||||
from models.dcm_task import DcmTask
|
||||
from paste.core.logging import echo_log
|
||||
from paste.util import udict
|
||||
from paste.web import requests
|
||||
|
||||
ApplyPostponeTmp = "apply_postpone_tmp"
|
||||
ApplyRollbackTmp = "apply_rollback_tmp"
|
||||
RollbackTmp = "rollback_tmp"
|
||||
TransitTmp = "transit_tmp"
|
||||
|
||||
MediaUsage = [ApplyPostponeTmp, ApplyRollbackTmp, RollbackTmp, TransitTmp]
|
||||
"""
|
||||
可用媒体对象。
|
||||
"""
|
||||
|
||||
|
||||
async def get_upload_request(dcm_task: DcmTask, media_usage: str, files: dict[str, io.IOBase],
|
||||
relation_sub_id: Optional[int] = None,
|
||||
relation_main_id: Optional[int] = 45):
|
||||
"""
|
||||
创建文件上传请求。因数字城管服务器仅接受单文档上传,因此返回的是请求对象列表。
|
||||
|
||||
:param dcm_task: 待办工单
|
||||
:param media_usage: 媒体使用
|
||||
:param files: 要上传的文件数据
|
||||
:param relation_sub_id: 可选参数
|
||||
:param relation_main_id: 可选参数
|
||||
:return: 上传请求列表
|
||||
"""
|
||||
api_url = f"/media/upload"
|
||||
assert media_usage in MediaUsage, f"参数错误,须为:{MediaUsage} 之一."
|
||||
|
||||
request_list = []
|
||||
_id = 0
|
||||
for key, value in files.items():
|
||||
request_body = {
|
||||
"relationTypeID": 10,
|
||||
"mediaUsage": media_usage,
|
||||
"checkExist": True,
|
||||
"relationID": dcm_task.rec_id,
|
||||
"relationSubID": relation_sub_id if relation_sub_id is not None else dcm_task.act_id,
|
||||
"relationMainID": relation_main_id,
|
||||
"tempUsage": media_usage,
|
||||
"id": f"WU_FILE_{_id}",
|
||||
"name": key,
|
||||
"type": 'image/png',
|
||||
"lastModifiedDate": datetime.datetime.now().strftime("%a %b %d %Y %H:%M:%S %z").replace(
|
||||
"+0800", "GMT+0800"
|
||||
),
|
||||
"size": len(value.read()),
|
||||
key: value,
|
||||
}
|
||||
_id += 1
|
||||
# 构造 API 请求
|
||||
request = await dcm_api.new_api_request(api_url, request_body)
|
||||
setattr(request, 'dcm_task', dcm_task)
|
||||
setattr(request, 'media_usage', media_usage)
|
||||
setattr(request, 'file_name', key)
|
||||
request_list.append(request)
|
||||
# 返回请求列表
|
||||
return request_list
|
||||
|
||||
|
||||
async def get_media_request(dcm_task: DcmTask, media_usage: str):
|
||||
"""
|
||||
创建读取 MediaID 请求。
|
||||
|
||||
:param dcm_task: 待办工单
|
||||
:param media_usage: 媒体使用
|
||||
:return: 上传请求列表
|
||||
"""
|
||||
api_url = f"/media/get"
|
||||
assert media_usage in MediaUsage, f"参数错误,须为:{MediaUsage} 之一."
|
||||
request_body = {
|
||||
"relationTypeID": 10,
|
||||
"mediaUsage": media_usage,
|
||||
"relationID": dcm_task.rec_id,
|
||||
"relationSubID": dcm_task.act_id,
|
||||
"relationMainID": 45,
|
||||
}
|
||||
# 构造 API 请求
|
||||
request = await dcm_api.new_api_request(api_url, request_body, method="GET")
|
||||
setattr(request, 'dcm_task', dcm_task)
|
||||
setattr(request, 'media_usage', media_usage)
|
||||
return request
|
||||
|
||||
|
||||
async def on_upload_error(request: HTTPRequest, exc: Exception, retry_queue: asyncio.Queue = None):
|
||||
"""
|
||||
下载附件时的出错处理。
|
||||
|
||||
:param request: 请求对象
|
||||
:param exc: 异常对象
|
||||
:param retry_queue:
|
||||
:return:
|
||||
"""
|
||||
retry = getattr(request, 'retry', 0)
|
||||
max_retry = getattr(request, 'max_retry', 0)
|
||||
if retry < max_retry - 1:
|
||||
# 非最后一次尝试,不处理
|
||||
return
|
||||
|
||||
dcm_task: DcmTask = getattr(request, 'dcm_task')
|
||||
media_usage = getattr(request, 'media_usage')
|
||||
file_name = getattr(request, 'file_name')
|
||||
message = f'工单ID:{dcm_task.id},类型为:{media_usage},文件名为:{file_name} 的附件上传失败.'
|
||||
echo_log(message)
|
||||
echo_log(exc, logging.ERROR, is_log_exc=True)
|
||||
|
||||
# 保存异常
|
||||
exc_list = getattr(dcm_task, 'exc_list')
|
||||
exc_list.append(PushException(message))
|
||||
|
||||
|
||||
async def after_upload_request(response: HTTPResponse, retry_queue: asyncio.Queue[HTTPRequest]):
|
||||
"""
|
||||
提交数字城管后的处理程序。
|
||||
|
||||
:param response: 响应对象
|
||||
:param retry_queue: 重试队列
|
||||
"""
|
||||
dcm_task: DcmTask = getattr(response.request, 'dcm_task')
|
||||
media_usage = getattr(response.request, 'media_usage')
|
||||
file_name = getattr(response.request, 'file_name')
|
||||
echo_log(response.body.decode())
|
||||
echo_log(f'工单ID:{dcm_task.id},类型为:{media_usage},文件名为:{file_name} 的附件上传成功.')
|
||||
|
||||
|
||||
async def push_upload(dcm_task: DcmTask, media_usage: str, files: dict[str, io.IOBase],
|
||||
relation_sub_id: Optional[int] = None,
|
||||
relation_main_id: Optional[int] = 45):
|
||||
"""
|
||||
向数字城管上传文件。
|
||||
|
||||
:param dcm_task: 待办工单
|
||||
:param media_usage: 媒体使用
|
||||
:param files: 要上传的文件数据
|
||||
:param relation_sub_id: 可选参数
|
||||
:param relation_main_id: 可选参数
|
||||
:return:
|
||||
"""
|
||||
echo_log(f"正在准备上传队列...")
|
||||
request_list = await get_upload_request(dcm_task, media_usage, files, relation_sub_id, relation_main_id)
|
||||
upload_request_queue = asyncio.Queue()
|
||||
for req in request_list:
|
||||
await upload_request_queue.put(req)
|
||||
|
||||
# 并发提交上传请求
|
||||
await requests.async_concurrency(
|
||||
upload_request_queue, con_count=dock.CONCURRENCY_COUNT, retry=dock.MAX_RETRY_COUNT,
|
||||
after_request=after_upload_request, on_error=on_upload_error
|
||||
)
|
||||
|
||||
# 上传后,读取文件 MediaID
|
||||
media_request = await get_media_request(dcm_task, media_usage)
|
||||
media_request_queue = asyncio.Queue()
|
||||
await media_request_queue.put(media_request)
|
||||
media_response_list: list[HTTPResponse] = await requests.async_concurrency(
|
||||
media_request_queue, con_count=dock.CONCURRENCY_COUNT, retry=dock.MAX_RETRY_COUNT
|
||||
)
|
||||
# 从响应列表中取得媒体ID和媒体类型ID
|
||||
media_id_list: list = []
|
||||
media_type_list: list = []
|
||||
media_num = 0
|
||||
if media_response_list:
|
||||
response = media_response_list[0]
|
||||
response_body = response.body.decode()
|
||||
response_data = json.loads(response_body)
|
||||
media_list = udict.get_by_path(response_data, 'data.mediaList')
|
||||
media_num = len(media_list)
|
||||
for media in media_list:
|
||||
media_id_list.append(f"{media.get('mediaID')}")
|
||||
media_type_list.append(media.get('mediaType'))
|
||||
|
||||
# 用英文逗号拼接后返回
|
||||
return ",".join(media_id_list), ",".join(media_type_list), media_num
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
from paste.core import aio_pool
|
||||
|
||||
_runner = aio_pool.get_aio_runner()
|
||||
Reference in New Issue
Block a user