edms.py 6.39 KB
import os
import requests
from zeep import Client, xsd
from settings import conf
from apps.doc import consts
from common.redis_cache import redis_handler as rh


class EDMS:

    def __init__(self):
        self.sm_client = Client(wsdl=conf.SM_WSDL)
        self.dm_client = Client(wsdl=conf.DM_WSDL)
        self.df_client = Client(wsdl=conf.DF_WSDL)
        self.rc_client = Client(wsdl=conf.RC_WSDL)
        self.download_url = conf.EDMS_DOWNLOAD_URL
        self.upload_url = conf.EDMS_UPLOAD_URL
        self.dealer_code = conf.DEALER_CODE

        self.user_name = conf.EDMS_USER
        self.pwd = conf.EDMS_PWD
        self.session_id = None
        self.prefix = 'OCR'

    def set_session_id(self):
        self.session_id = self.sm_client.service.StartSession(login=self.user_name,
                                                              password=self.pwd,
                                                              clientType=consts.CUSTOM_CLIENT)
        rh.set_session_id(self.session_id)
        return self.session_id

    def get_session_id(self):
        if self.session_id is None:
            # redis获取session_id
            self.session_id = rh.get_session_id()
            if self.session_id is None:
                return self.set_session_id()
        # 验证session_id
        is_session_valid = self.sm_client.service.IsSessionValid(sessionId=self.session_id, keepAlive=False)
        if is_session_valid is True:
            return self.session_id
        return self.set_session_id()

    def get_headers(self):
        session_id = self.get_session_id()
        headers = {'Cookie': '{0}={1}'.format(consts.SESSION_PREFIX, session_id)}
        return headers

    def get_download_token(self, headers, metadata_version_id):
        with self.dm_client.settings(extra_http_headers=headers):
            res = self.dm_client.service.PrepareSingleDocumentToDownload(metadataVersionId=metadata_version_id,
                                                                         token=consts.FIXED_TOKEN,
                                                                         fileSize=consts.FIXED_FILE_SIZE,
                                                                         actionType=consts.DOWNLOAD_ACTION_TYPE)
        return res.token

    def download_handler(self, params, headers, save_path):
        r = requests.get(self.download_url, params=params, headers=headers, stream=True)
        with open(save_path, "wb") as f:
            # chunk是指定每次写入的大小,每次只写了512byte
            for chunk in r.iter_content(chunk_size=1024):
                if chunk:
                    f.write(chunk)
                    f.flush()

    def download(self, save_path, metadata_version_id):
        headers = self.get_headers()
        token = self.get_download_token(headers, metadata_version_id)
        params = {'token': token}
        self.download_handler(params, headers, save_path)

    def create_upload_token(self, headers):
        with self.rc_client.settings(extra_http_headers=headers):
            token = self.rc_client.service.CreateUploadToken(fileSize=consts.FIXED_FILE_SIZE)
        return token

    def upload_handler(self, file_path, params, headers):
        with open(file_path, 'rb') as f:
            data = f.read()
        for retry in range(4):
            res = requests.post(self.upload_url, params=params, headers=headers, data=data)
            if res.status_code == requests.codes.ok:
                break
        else:
            raise Exception

    def get_doc_file_name(self, doc_name):
        if not isinstance(doc_name, str):
            return self.prefix
        if doc_name.endswith('.pdf') or doc_name.endswith('.PDF') or \
                doc_name.endswith('.pdF') or doc_name.endswith('.pDF') or doc_name.endswith('.pDf') or \
                doc_name.endswith('.Pdf') or doc_name.endswith('.PdF') or doc_name.endswith('.PDf'):
            name, _ = os.path.splitext(doc_name)
            return '{0}{1}'.format(self.prefix, name)
        return '{0}{1}'.format(self.prefix, doc_name)

    def get_doc_info(self, token, doc, business_type, file_path):
        business_type = consts.BUSINESS_TYPE_DICT.get(business_type)
        doc_schema_id, auto_filing = consts.DOC_SCHEMA_ID_FILL.get(doc.document_scheme)
        application_id = doc.application_id
        doc_file_name = self.get_doc_file_name(doc.document_name)
        origin_file_name = os.path.basename(file_path)
        fields_with_value = [
            {'FieldId': consts.APPLICATION_ID_META_FIELD_id,
             'FieldValue': xsd.AnyObject(xsd.String(), application_id)},
            {'FieldId': consts.DEALER_CODE_META_FIELD_id,
             'FieldValue': xsd.AnyObject(xsd.String(), self.dealer_code)},
            {'FieldId': consts.BUSINESS_TYPE_META_FIELD_id,
             'FieldValue': xsd.AnyObject(xsd.String(), business_type)},
        ]
        fields_with_values = {'FieldWithValue': fields_with_value}
        info = {
            'DocumentSchemaId': doc_schema_id,
            'DocumentName': doc_file_name,
            'FieldsWithValues': fields_with_values,
            'UploadToken': token,
            'OriginalFileName': origin_file_name,
            'SendEmailToMembers': False,
            'AutoFilingScriptToUse': auto_filing,
            'DocumentSchemaType': consts.DOC_SCHEMA_TYPE,
        }
        return info

    def add_doc_info(self, headers, token, doc, business_type, file_path):
        info = self.get_doc_info(token, doc, business_type, file_path)
        with self.dm_client.settings(extra_http_headers=headers):
            metadata_version_id = self.dm_client.service.AddDocumentInfo(info=info)
        return metadata_version_id

    def upload(self, file_path, doc, business_type):
        # file_path = '/Users/clay/Postman/files/OCRuploadTest4.txt'
        # file_size = 16
        # doc_info = {
        #     'document_scheme': 'Acceptance',
        #     'application_id': 'CH-B100014248',
        #     'doc_file_name': 'OCRuploadTest4.txt',
        #     'business_type': 'CO00001',
        # }
        headers = self.get_headers()
        token = self.create_upload_token(headers)
        headers.update({'Content-Type': 'application/octet-stream'})
        params = {'token': token}
        self.upload_handler(file_path, params, headers)
        headers.pop('Content-Type')
        metadata_version_id = self.add_doc_info(headers, token, doc, business_type, file_path)
        return metadata_version_id