labkeyFileBrowser.py 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. import urllib3
  2. import xml.etree.ElementTree as ET
  3. import shutil
  4. import io
  5. class labkeyFileBrowser:
  6. def __init__(self,net):
  7. self.net=net
  8. def GetRootUrl(self):
  9. return self.net.GetLabkeyUrl()+"/_webdav"
  10. def entryExists(self,url):
  11. #check if entry (file/directory) exists
  12. r=self.net.head(url)
  13. if r.status==200:
  14. return True
  15. return False
  16. def listRemoteDir(self,url):
  17. #input is remoteDir, result are remoteDirs
  18. dirs=[]
  19. #r=MethodRequest(dirUrl,method="PROPFIND")
  20. PROPFIND=u"""<?xml version="1.0" encoding="utf-8"?>\n
  21. <propfind xmlns="DAV:">\n
  22. <prop>\n
  23. <getetag/>\n
  24. </prop>\n
  25. </propfind>"""
  26. headers=urllib3.util.make_headers(basic_auth=self.net.getBasicAuth())
  27. headers["Content-Type"]='text/xml; charset="utf-8"'
  28. headers['content-length']=str(len(PROPFIND))
  29. headers['Depth']='1'
  30. #add csrf
  31. headers["X-LABKEY-CSRF"]=self.net.getCSRF()
  32. try:
  33. f=self.net.http.request('PROPFIND',url,headers=headers,body=PROPFIND)
  34. #f contains json as a return value
  35. except urllib3.exceptions.HTTPError as e:
  36. print(e)
  37. return False,dirs
  38. try:
  39. tree=ET.XML(f.data)
  40. except ET.ParseError:
  41. #print(f.data.decode('utf-8'))
  42. #if directory is not there, a 404 response will be made by HTTP, which is not an xml file
  43. #we are safe to assume the directory is not there
  44. return False,dirs
  45. rps=tree.findall('{DAV:}response')
  46. for r in rps:
  47. hr=r.find('{DAV:}href')
  48. dirent=hr.text
  49. #dirent=re.sub('/labkey/_webdav/','',dirent)
  50. dirent=self.net.connectionConfig['host']+dirent
  51. dirs.append(dirent)
  52. del dirs[0]
  53. return True,dirs
  54. def buildPathURL(self,project,pathList):
  55. #build/check remote directory structure
  56. remoteDir=self.formatPathURL(project,'')
  57. for p in pathList:
  58. remoteDir+='/'+p
  59. if not self.entryExists(remoteDir):
  60. self.mkdir(remoteDir)
  61. return remoteDir
  62. def readFileToBuffer(self, url):
  63. response=self.net.get(url,binary=True)
  64. buffer=io.BytesIO()
  65. chunk=65532
  66. for chunk in response.stream(1024):
  67. buffer.write(chunk)
  68. response.release_conn()
  69. buffer.seek(0,0)
  70. return buffer
  71. def readFileToFile(self,url,path):
  72. response=self.net.get(url,binary=True)
  73. with open(path,'wb') as out_file:
  74. shutil.copyfileobj(response,out_file)
  75. response.release_conn()
  76. def writeFileToFile(self,path,url):
  77. with open(path,'rb') as f:
  78. data=f.read()
  79. self.net.put(url,data)
  80. def formatPathURL(self,project,path):
  81. url=self.GetRootUrl()+'/'+project+'/@files'
  82. if len(path)==0:
  83. return url
  84. return url+'/'+path
  85. def mkdir(self,url):
  86. self.net.mkcol(url)
  87. #listing helping functions
  88. def baseDir(self,remotePath):
  89. #strip potential trailing slash
  90. if remotePath[-1]=='/':
  91. remotePath=remotePath[:-1]
  92. #find last slash
  93. if remotePath.rfind('/')>-1:
  94. remotePath=remotePath[remotePath.rfind('/')+1:]
  95. return remotePath