Invoke Banner BDM ApplicationExtender Service API
Due to the situation of Conorvius, all stuff in my university works from home.
In order to forward fax to BDM directly, we asked DSG to convert fax to PDF to a shared folder at first.
And then, I am writing a python code to invoke ApplicationExtender API to index PDFs to a new created app.
I have done the code for the Login, Logout, CreateNewDocument, unlockDocumentByRef, CreateBatchPage, and UploadImageStream.
But unfortunately, CreateBatchPage and UploadImageStream are not working.
The document of ApplicationExtender is ridiculous, full of the error.
And there is no way for debuging.
We are using RESTful API to upload file as batch. In stead of going on the research of CreateBatchPage and UploadImageStream to save the time.
The code will iterator files in one folder, then, call CreateNewDocument to index each PDF with two field: ID and Time.
import xml.dom.minidom
from xml.dom.minidom import parse, parseString
import requests
import base64
import os
import datetime
import sys
import smtplib
user = 'user'
password = 'password'
datasource = 'datasource'
class AxServices:
# constant variable
url = 'https://xxx.odu.edu/AppXtenderServices/axservicesinterface.asmx'
xsi = 'http://www.w3.org/2001/XMLSchema-instance'
xsd = 'http://www.w3.org/2001/XMLSchema'
ax = 'http://www.emc.com/ax'
true = "true"
false = "false"
buffer_size = 8192
# classes
class AxObject:
def __init__(self, tag, attr):
self.doc = xml.dom.minidom.Document()
self.data = self.doc.createElement('ax:' + tag)
self.data.setAttribute('xmlns:xsi', AxServices.xsi)
self.data.setAttribute('xmlns:xsd', AxServices.xsd)
for key in attr:
self.data.setAttribute(key, attr[key])
self.data.setAttribute('xmlns:ax', AxServices.ax)
self.doc.appendChild(self.data)
def getData(self):
return self.data
def toXML(self):
return self.doc.toxml('utf-8').decode()
class AxDocCrtData(AxObject):
def __init__(self, appid, dsn, filepath):
attr = {}
attr['dsn'] = dsn
attr['appid'] = appid
attr['filepath'] = filepath
attr['filetype'] = 'FT_PDF' # AxTypes.FileType
# FT_UNKNOWN = 0 / FT_Text = 1 / FT_CompressedText = 2
# FT_ForeignFile = 3 / FT_OLE = 4 / FT_RTF = 5
# FT_HTML = 6 / FT_PDF = 7 / FT_IMAGE = 8 / FT_Annotation = 255
attr['ignore_dls'] = AxServices.true # Indicates whether to ignore document-level security checking while saving index values
attr['ignore_dup_index'] = AxServices.true # Indicates whether to ignore duplicated indexes while saving index values
attr['splitimg'] = AxServices.true # Indicates whether to split multi-page image files such as PDF, TIFF, and text.
attr['subpages'] = '0' # Number of sub-pages in the image file
super().__init__('AxDocCrtData', attr)
class QueryItem(AxObject):
def __init__(self):
attr = {}
attr['id'] = '-1'
super().__init__('QueryItem', attr)
data = super().getData()
self.attributes = self.doc.createElement('ax:Attributes')
self.fields = self.doc.createElement('ax:Fields')
data.appendChild(self.attributes)
data.appendChild(self.fields)
def addAttribute(self):
print('addAttribute')
def addField(self, id, val, nul):
field = self.doc.createElement('ax:Field')
field.setAttribute('id', str(id))
field.setAttribute('value', str(val))
field.setAttribute('isnull', str(nul))
self.fields.appendChild(field)
class AxPageUploadData(AxObject):
def __init__(self, filepath):
attr = {}
attr['act'] = 'InsertAfter'
attr['filepath'] = filepath
attr['filetype'] = 'FT_PDF'
attr['position'] = '1'
attr['splitimg'] = AxServices.true
attr['subpages'] = '0'
super().__init__('AxImgUploadData', attr)
class AxStreamData(AxObject):
def __init__(self, key, fname, data, startpos):
print(startpos)
self.attr = {}
self.attr['encryption'] = AxServices.false
self.attr['key'] = key
self.attr['origFile'] = fname
self.attr['startbyte'] = str(startpos)
self.attr['len'] = str(AxServices.buffer_size)
super().__init__('AxStreamData', self.attr)
sdata = super().getData();
sdata.setAttribute('ImageBytes', str(base64.b64encode(data)))
class Request:
header = {}
action_dict = {'Login': 'Login',
'CreateNewDocument': 'CreateNewDocument',
'CreateBatchPage': 'CreateBatchPage',
'UploadImageStream': 'UploadImageStream',
'Logout':'Logout',
'UnlockDocumentByRef':'UnlockDocumentByRef'
}
def __init__(self, data):
self.header['Content-Type'] = 'text/xml; charset=utf-8'
self.header['Host'] = 'xxxx.odu.edu'
self.header['SOAPAction'] = "http://documentum.com/AX/WebServices" + '/' + self.action_dict[type(self).__name__]
self.doc=''
self.response=''
self.setBody(data)
def setBody(self, data):
self.doc = xml.dom.minidom.Document()
envelope = self.doc.createElement('soap:Envelope')
envelope.setAttribute('xmlns:soap', 'http://schemas.xmlsoap.org/soap/envelope/')
envelope.setAttribute('xmlns:xsi', AxServices.xsi)
envelope.setAttribute('xmlns:xsd', AxServices.xsd)
self.doc.appendChild(envelope)
body = self.doc.createElement('soap:Body')
envelope.appendChild(body)
action = self.doc.createElement(self.action_dict[type(self).__name__])
action.setAttribute('xmlns', 'http://documentum.com/AX/WebServices')
body.appendChild(action)
for key in data:
ele = self.doc.createElement(key)
ele.appendChild(self.doc.createTextNode(str(self.data[key])))
action.appendChild(ele)
return body
def toXML(self):
return self.doc.toxml('utf-8').decode()
def toPXML(self):
return self.doc.toprettyxml(' ')
def getBody(self):
return self.toXML()
def post(self):
self.response = requests.post(AxServices.url, headers=self.header, data=self.getBody())
return self.response.status_code
def getResponse(self):
return self.response;
def getResponseText(self):
self.response.encoding = 'utf-8'
return self.response.text;
def getResponseBody(self):
xml = self.getResponseText();
dom = parseString(xml)
return dom.getElementsByTagName("soap:Envelope")[0].getElementsByTagName("soap:Body")[0]
def getResponseResult(self):
return self.getResponseBody().firstChild.firstChild.firstChild.nodeValue
def getEleByTagFromResponse(self, tag):
retxml = self.getResponseResult();
return xml.dom.minidom.parseString(retxml).getElementsByTagName(tag)
class Login(Request):
def __init__(self, ds, user, password):
self.data = {'sessionTicket': '', 'dataSource': ds, 'userId': user, 'password': password, 'features': 1}
super().__init__(self.data)
def getSessionTicket(self):
return super().getResponseResult()
class Logout(Request):
def __init__(self, ticket):
self.data = {'sessionTicket': ticket}
super().__init__(self.data)
class CreateNewDocument(Request):
def __init__(self, ticket, data, idx):
self.data = {'sessionTicket': ticket, 'xmlAxDocumentCreationData': str(data), 'xmlDocIndex': str(idx)}
super().__init__(self.data)
def getDoc(self):
return super().getEleByTagFromResponse('ax:Doc')[0]
def getDocID(self):
return self.getDoc().getAttribute('id')
def getRef(self):
return self.getDoc().getAttribute('objref')
class UnlockDocumentByRef(Request):
def __init__(self, ticket, ref):
self.data = {'sessionTicket': ticket, 'docReference': ref}
super().__init__(self.data)
class CreateBatchPage(Request):
def __init__(self, ticket, ds, appid, batchname, data):
self.data = {'sessionTicket': ticket, 'dataSource': ds, 'appid': appid, 'batchname': batchname, 'xmlPageUploadData': str(data)}
super().__init__(self.data)
class UploadImageStream(Request):
def __init__(self, ticket, ds, data):
self.data = {'sessionTicket': ticket, 'dataSource': ds, 'xmlAxStreamData': str(data)}
super().__init__(self.data)
def getUploadKey(self):
body = super().getResponseBody()
return body.firstChild.firstChild.firstChild.nodeValue
# functions
def __init__(self):
self.sessionTicket = ''
self.dataSource = ''
def login(self, ds, user, password):
obj = self.Login(ds, user, password)
ret = obj.post()
if ret == 200:
print("login successfully")
self.sessionTicket = obj.getSessionTicket()
self.dataSource = ds
else:
raise Exception(ret, obj.getResponseText())
return self.sessionTicket
def logout(self):
obj = self.Logout(self.sessionTicket)
ret = obj.post()
if ret != 200:
raise Exception(ret, obj.getResponseText())
def getSessionTicket(self):
return self.sessionTicket;
def getDataSource(self):
return self.dataSource;
def createnewdocument(self, data, idx):
obj = self.CreateNewDocument(self.sessionTicket, data.toXML(), idx.toXML())
ret = obj.post()
if ret == 200:
print('success, doc id: ' + obj.getDocID() + ' ref: ' + obj.getRef())
return obj.getRef()
else:
raise Exception(ret, obj.getResponseText())
def unlockdocumentbyref(self, ref):
obj = self.UnlockDocumentByRef(self.sessionTicket, ref)
ret = obj.post()
if ret != 200:
raise Exception(ret, obj.getResponseText())
def createbatchpage(self, appid, batchname, data):
obj = self.CreateBatchPage(self.sessionTicket, self.dataSource, appid, batchname, data.toXML())
ret = obj.post()
if ret == 200:
print('success')
else:
raise Exception(ret, obj.getResponseText())
def uploadimagestream(self, data):
obj = self.UploadImageStream(self.sessionTicket, self.dataSource, data.toXML())
ret = obj.post()
if ret == 200:
return obj.getUploadKey()
else:
raise Exception(ret, obj.getResponseText())
def uploadfile(self, filename):
head, tail = os.path.split(filename)
file = open(filename, 'rb', self.buffer_size)
idx = 0
key = ''
while True:
print(key)
data = file.read(self.buffer_size)
if not data:
break
sdata = srv.AxStreamData(key, tail, data, idx * self.buffer_size)
key = srv.uploadimagestream(sdata)
idx = idx+1
return key
def indexDocByFolder(self, appid, dir, tpath, fpath):
failed = 0
first = True;
seq = 0;
for file in os.listdir(dir):
seq = seq + 1
filePath = str(dir)+'/' + str(file)
tgtPath = str(tpath) + '/' + str(file)
faildPath = str(fpath) + '/' + str(file)
if file.upper().endswith('.PDF'):
# t = datetime.datetime.now()
t = datetime.datetime.fromtimestamp(os.path.getmtime(filePath))
id = str(appid) + '_' + str(file).replace(' ', '_').replace('.','_').replace('(','').replace(')','') + '_' + str(t.strftime('%Y%m%d%H%M%S')) + '_' + str(seq)
print("[START] "+ filePath + "," + id)
data = srv.AxDocCrtData(str(appid), self.dataSource, filePath)
idx = srv.QueryItem()
idx.addField(1, id, AxServices.false)
#idx.addField(2, t.strftime('%Y-%m-%d %H:%M:%S'), AxServices.false)
idx.addField(2, t.strftime('%m-%d-%Y'), AxServices.false)
try:
ref = srv.createnewdocument(data, idx)
srv.unlockdocumentbyref(ref)
os.rename(filePath, tgtPath)
except Exception as e:
os.rename(os.rename(filePath, failedPath))
failed = failed + 1
print("[END] " + filePath)
print(str(seq) + " files processed, " + str(failed) + " failed.")
return seq, failed
if __name__ == "__main__":
if len(sys.argv) != 5:
print('Four Args, appid, source path, processed path, and failed path')
exit(-1)
appid = sys.argv[1]
spath = sys.argv[2]
tpath = sys.argv[3]
fpath = sys.argv[4]
failed = 0
try:
srv = AxServices()
ticket = srv.login(datasource, user, password)
processed, failed = srv.indexDocByFolder(appid, spath, tpath, fpath)
srv.logout()
if failed > 0:
failed = -1
raise Exception('400','login failed')
except Exception as e:
smtp = smtplib.SMTP('smtp.odu.edu')
smtp.sendmail('dba-dist@odu.edu','dba-dist@odu.edu','[BDM Automation]: '+ str(failed) + ' failed.')
# CreateNewDocument
# data = srv.AxDocCrtData('509', srv.dataSource, 'c:/bdm_file/test.pdf')
# idx = srv.QueryItem()
# import random
# idx.addField(1, str(random.randint(80000,90000)), AxServices.false)
# idx.addField(2, '45237', AxServices.false)
# idx.addField(3, 'REF4', AxServices.false)
# idx.addField(14, 'UI', AxServices.false)
# srv.createnewdocument(data, idx)
# CreateBatchPage
# data1 = srv.AxPageUploadData('c:/bdm_file/test.pdf')
# print(data1.toXML())
# data2 = srv.AxPageUploadData('c:/bdm_file/test.pdf')
# srv.createbatchpage( '509', 'batch1', data1)
# UploadImageStream
# filekey = srv.uploadfile('C:/Users/q1zhang/Downloads/test2.pdf')
# data = srv.AxDocCrtData('509', srv.dataSource, filekey)
# idx = srv.QueryItem()
# idx.addField(1, '78538', AxServices.false)
# idx.addField(2, '45237', AxServices.false)
# idx.addField(3, 'REF4', AxServices.false)
# idx.addField(14, 'UI', AxServices.false)
# srv.createnewdocument(data, idx)