def upload_file(self, remote_path, local_path, progress=None): """Uploads file to remote path on WebDAV server. File should be 2Gb or less. More information you can find by link http://webdav.org/specs/rfc4918.html#METHOD_PUT :param remote_path: the path to uploading file on WebDAV server. :param local_path: the path to local file for uploading. :param progress: Progress function. Not supported now. """ if not os.path.exists(local_path): raise LocalResourceNotFound(local_path) urn = Urn(remote_path) if urn.is_dir(): raise OptionNotValid(name='remote_path', value=remote_path) if os.path.isdir(local_path): raise OptionNotValid(name='local_path', value=local_path) if not self.check(urn.parent()): raise RemoteParentNotFound(urn.path()) with open(local_path, 'rb') as local_file: file_size = os.path.getsize(local_path) if file_size > self.large_size: raise ResourceTooBig(path=local_path, size=file_size, max_size=self.large_size) self.execute_request(action='upload', path=urn.quote(), data=local_file)
def mkdir(self, remote_path): try: directory_urn = Urn(remote_path, directory=True) if not self.check(directory_urn.parent()): raise RemoteParentNotFound(directory_urn.path()) url = { 'hostname': self.webdav.hostname, 'root': self.webdav.root, 'path': directory_urn.quote() } options = { 'URL': "{hostname}{root}{path}".format(**url), 'CUSTOMREQUEST': Client.requests['mkdir'], 'HTTPHEADER': self.get_header('mkdir') } request = self.Request(options=options) request.perform() request.close() except pycurl.error: raise NotConnection(self.webdav.hostname)
def upload_from(self, buff, remote_path): try: urn = Urn(remote_path) if urn.is_dir(): raise OptionNotValid(name="remote_path", value=remote_path) if not self.check(urn.parent()): raise RemoteParentNotFound(urn.path()) url = {'hostname': self.webdav.hostname, 'root': self.webdav.root, 'path': urn.quote()} options = { 'URL': "{hostname}{root}{path}".format(**url), 'HTTPHEADER': self.get_header('upload_from'), 'UPLOAD': 1, 'READFUNCTION': buff.read, } request = self.Request(options=options) request.perform() code = request.getinfo(pycurl.HTTP_CODE) if code == "507": raise NotEnoughSpace() request.close() except pycurl.error: raise NotConnection(self.webdav.hostname)
def upload_from(self, buff, remote_path): try: urn = Urn(remote_path) if urn.is_dir(): raise OptionNotValid(name="remote_path", value=remote_path) if not self.check(urn.parent()): raise RemoteParentNotFound(urn.path()) url = { 'hostname': self.webdav.hostname, 'root': self.webdav.root, 'path': urn.quote() } options = { 'URL': "{hostname}{root}{path}".format(**url), 'HTTPHEADER': self.get_header('upload_from'), 'UPLOAD': 1, 'READFUNCTION': buff.read, } request = self.Request(options=options) request.perform() code = request.getinfo(pycurl.HTTP_CODE) if code == "507": raise NotEnoughSpace() request.close() except pycurl.error: raise NotConnection(self.webdav.hostname)
def check(self, remote_path=root): def parse(response, path): try: response_str = response.getvalue() tree = etree.fromstring(response_str) resps = tree.findall("{DAV:}response") for resp in resps: href = resp.findtext("{DAV:}href") urn = unquote(href) if path.endswith(Urn.separate): if path == urn or path[:-1] == urn: return True else: if path == urn: return True return False except etree.XMLSyntaxError: raise MethodNotSupported(name="check", server=self.webdav.hostname) try: urn = Urn(remote_path) parent_urn = Urn(urn.parent()) response = BytesIO() url = { 'hostname': self.webdav.hostname, 'root': self.webdav.root, 'path': parent_urn.quote() } options = { 'URL': "{hostname}{root}{path}".format(**url), 'CUSTOMREQUEST': Client.requests['info'], 'HTTPHEADER': self.get_header('info'), 'WRITEDATA': response, 'NOBODY': 0 } request = self.Request(options=options) request.perform() request.close() path = "{root}{path}".format(root=self.webdav.root, path=urn.path()) return parse(response, path) except pycurl.error: raise NotConnection(self.webdav.hostname)
def upload(self, source_stream, device_path, chunk_size=8192): with self._internal_lock: self.is_remote_available.wait() self.logger.debug(self._prefix + "Uploading " + str(device_path)) iter = 0 while 1: self.is_remote_available.wait() already_sent = 0 # всегда начинаем сначала try: source_stream.seek(already_sent) # self._wc.upload_from(source_stream, device_path) try: urn = Urn(device_path) if urn.is_dir(): raise OptionNotValid(name="device_path", value=device_path) if not self._wc.check(urn.parent()): raise RemoteParentNotFound(urn.path()) url = {'hostname': self._wc.webdav.hostname, 'root': self._wc.webdav.root, 'path': urn.quote()} options = { 'URL': "{hostname}{root}{path}".format(**url), 'HTTPHEADER': self._wc.get_header('upload_from'), 'UPLOAD': 1, 'READFUNCTION': source_stream.read, } request = self._wc.Request(options=options) request.perform() code = request.getinfo(pycurl.HTTP_CODE) if str(code) == "507": # raise NotEnoughSpace() raise Exception("Not enough space on the server") request.close() except pycurl.error: raise NotConnection(self._wc.webdav.hostname) break except Exception as ex: iter += 1 if iter == 3: self.logger.error(self._prefix + "Uploading was interrupted " + str(iter) + " times: " + str(ex)) break else: self.logger.error(self._prefix + "Uploading was interrupted " + str(iter) + " times: " + str(ex)) time.sleep(1)
def upload_file(self, remote_path, local_path, progress=None): try: if not os.path.exists(local_path): raise LocalResourceNotFound(local_path) urn = Urn(remote_path) if urn.is_dir(): raise OptionNotValid(name="remote_path", value=remote_path) if os.path.isdir(local_path): raise OptionNotValid(name="local_path", value=local_path) if not os.path.exists(local_path): raise LocalResourceNotFound(local_path) if not self.check(urn.parent()): raise RemoteParentNotFound(urn.path()) with open(local_path, "rb") as local_file: url = { 'hostname': self.webdav.hostname, 'root': self.webdav.root, 'path': urn.quote() } options = { 'URL': "{hostname}{root}{path}".format(**url), 'HTTPHEADER': self.get_header('upload_file'), 'UPLOAD': 1, 'READFUNCTION': local_file.read, 'NOPROGRESS': 0 if progress else 1 } if progress: options["PROGRESSFUNCTION"] = progress file_size = os.path.getsize(local_path) if file_size > self.large_size: options['INFILESIZE_LARGE'] = file_size else: options['INFILESIZE'] = file_size request = self.Request(options=options) request.perform() code = request.getinfo(pycurl.HTTP_CODE) if code == "507": raise NotEnoughSpace() request.close() except pycurl.error: raise NotConnection(self.webdav.hostname)
def upload_file(self, remote_path, local_path, progress=None): try: if not os.path.exists(local_path): raise LocalResourceNotFound(local_path) urn = Urn(remote_path) if urn.is_dir(): raise OptionNotValid(name="remote_path", value=remote_path) if os.path.isdir(local_path): raise OptionNotValid(name="local_path", value=local_path) if not os.path.exists(local_path): raise LocalResourceNotFound(local_path) if not self.check(urn.parent()): raise RemoteParentNotFound(urn.path()) with open(local_path, "rb") as local_file: url = {'hostname': self.webdav.hostname, 'root': self.webdav.root, 'path': urn.quote()} options = { 'URL': "{hostname}{root}{path}".format(**url), 'HTTPHEADER': self.get_header('upload_file'), 'UPLOAD': 1, 'READFUNCTION': local_file.read, 'NOPROGRESS': 0 if progress else 1 } if progress: options["PROGRESSFUNCTION"] = progress file_size = os.path.getsize(local_path) if file_size > self.large_size: options['INFILESIZE_LARGE'] = file_size else: options['INFILESIZE'] = file_size request = self.Request(options=options) request.perform() code = request.getinfo(pycurl.HTTP_CODE) if code == "507": raise NotEnoughSpace() request.close() except pycurl.error: raise NotConnection(self.webdav.hostname)
def check(self, remote_path=root): def parse(response, path): try: response_str = response.getvalue() tree = etree.fromstring(response_str) resps = tree.findall("{DAV:}response") for resp in resps: href = resp.findtext("{DAV:}href") urn = unquote(href) if path.endswith(Urn.separate): if path == urn or path[:-1] == urn: return True else: if path == urn: return True return False except etree.XMLSyntaxError: raise MethodNotSupported(name="check", server=self.webdav.hostname) try: urn = Urn(remote_path) parent_urn = Urn(urn.parent()) response = BytesIO() url = {'hostname': self.webdav.hostname, 'root': self.webdav.root, 'path': parent_urn.quote()} options = { 'URL': "{hostname}{root}{path}".format(**url), 'CUSTOMREQUEST': Client.requests['info'], 'HTTPHEADER': self.get_header('info'), 'WRITEDATA': response, 'NOBODY': 0 } request = self.Request(options=options) request.perform() request.close() path = "{root}{path}".format(root=self.webdav.root, path=urn.path()) return parse(response, path) except pycurl.error: raise NotConnection(self.webdav.hostname)
def upload_to(self, buff, remote_path): """Uploads file from buffer to remote path on WebDAV server. More information you can find by link http://webdav.org/specs/rfc4918.html#METHOD_PUT :param buff: the buffer with content for file. :param remote_path: the path to save file remotely on WebDAV server. """ urn = Urn(remote_path) if urn.is_dir(): raise OptionNotValid(name='remote_path', value=remote_path) if not self.check(urn.parent()): raise RemoteParentNotFound(urn.path()) self.execute_request(action='upload', path=urn.quote(), data=buff)
def is_dir(self, remote_path): """Checks is the remote resource directory. More information you can find by link http://webdav.org/specs/rfc4918.html#METHOD_PROPFIND :param remote_path: the path to remote resource. :return: True in case the remote resource is directory and False otherwise. """ urn = Urn(remote_path) parent_urn = Urn(urn.parent()) if not self.check(urn.path()) and not self.check( Urn(remote_path, directory=True).path()): raise RemoteResourceNotFound(remote_path) response = self.execute_request(action='info', path=parent_urn.quote()) path = self.get_full_path(urn) return WebDavXmlUtils.parse_is_dir_response( content=response.content, path=path, hostname=self.webdav.hostname)
def copy(self, remote_path_from, remote_path_to): def header(remote_path_to): path = Urn(remote_path_to).path() destination = "{root}{path}".format(root=self.webdav.root, path=path) header_item = "Destination: {destination}".format( destination=destination) header = self.get_header('copy') header.append(header_item) return header try: urn_from = Urn(remote_path_from) if not self.check(urn_from.path()): raise RemoteResourceNotFound(urn_from.path()) urn_to = Urn(remote_path_to) if not self.check(urn_to.parent()): raise RemoteParentNotFound(urn_to.path()) url = { 'hostname': self.webdav.hostname, 'root': self.webdav.root, 'path': urn_from.quote() } options = { 'URL': "{hostname}{root}{path}".format(**url), 'CUSTOMREQUEST': Client.requests['copy'], 'HTTPHEADER': header(remote_path_to) } request = self.Request(options=options) request.perform() request.close() except pycurl.error: raise NotConnection(self.webdav.hostname)
def copy(self, remote_path_from, remote_path_to): """Copies resource from one place to another on WebDAV server. More information you can find by link http://webdav.org/specs/rfc4918.html#METHOD_COPY :param remote_path_from: the path to resource which will be copied, :param remote_path_to: the path where resource will be copied. """ urn_from = Urn(remote_path_from) if not self.check(urn_from.path()): raise RemoteResourceNotFound(urn_from.path()) urn_to = Urn(remote_path_to) if not self.check(urn_to.parent()): raise RemoteParentNotFound(urn_to.path()) header_destination = f'Destination: {self.get_full_path(urn_to)}' self.execute_request(action='copy', path=urn_from.quote(), headers_ext=[header_destination])
def mkdir(self, remote_path): try: directory_urn = Urn(remote_path, directory=True) if not self.check(directory_urn.parent()): raise RemoteParentNotFound(directory_urn.path()) url = {'hostname': self.webdav.hostname, 'root': self.webdav.root, 'path': directory_urn.quote()} options = { 'URL': "{hostname}{root}{path}".format(**url), 'CUSTOMREQUEST': Client.requests['mkdir'], 'HTTPHEADER': self.get_header('mkdir') } request = self.Request(options=options) request.perform() request.close() except pycurl.error: raise NotConnection(self.webdav.hostname)
def move(self, remote_path_from, remote_path_to, overwrite=False): """Moves resource from one place to another on WebDAV server. More information you can find by link http://webdav.org/specs/rfc4918.html#METHOD_MOVE :param remote_path_from: the path to resource which will be moved, :param remote_path_to: the path where resource will be moved. :param overwrite: (optional) the flag, overwrite file if it exists. Defaults is False """ urn_from = Urn(remote_path_from) if not self.check(urn_from.path()): raise RemoteResourceNotFound(urn_from.path()) urn_to = Urn(remote_path_to) if not self.check(urn_to.parent()): raise RemoteParentNotFound(urn_to.path()) header_destination = f'Destination: {self.get_full_path(urn_to)}' header_overwrite = f'Overwrite: {"T" if overwrite else "F"}' self.execute_request( action='move', path=urn_from.quote(), headers_ext=[header_destination, header_overwrite])
def copy(self, remote_path_from, remote_path_to): def header(remote_path_to): path = Urn(remote_path_to).path() destination = "{root}{path}".format(root=self.webdav.root, path=path) header_item = "Destination: {destination}".format(destination=destination) header = self.get_header('copy') header.append(header_item) return header try: urn_from = Urn(remote_path_from) if not self.check(urn_from.path()): raise RemoteResourceNotFound(urn_from.path()) urn_to = Urn(remote_path_to) if not self.check(urn_to.parent()): raise RemoteParentNotFound(urn_to.path()) url = {'hostname': self.webdav.hostname, 'root': self.webdav.root, 'path': urn_from.quote()} options = { 'URL': "{hostname}{root}{path}".format(**url), 'CUSTOMREQUEST': Client.requests['copy'], 'HTTPHEADER': header(remote_path_to) } request = self.Request(options=options) request.perform() request.close() except pycurl.error: raise NotConnection(self.webdav.hostname)
def is_dir(self, remote_path): def parse(response, path): try: response_str = response.getvalue() tree = etree.fromstring(response_str) resps = tree.findall("{DAV:}response") for resp in resps: href = resp.findtext("{DAV:}href") urn = unquote(href) if path[-1] == Urn.separate: if not path == urn: continue else: path_with_sep = "{path}{sep}".format(path=path, sep=Urn.separate) if not path == urn and not path_with_sep == urn: continue type = resp.find(".//{DAV:}resourcetype") if type is None: raise MethodNotSupported(name="is_dir", server=self.webdav.hostname) dir_type = type.find("{DAV:}collection") return True if dir_type is not None else False raise RemoteResourceNotFound(path) except etree.XMLSyntaxError: raise MethodNotSupported(name="is_dir", server=self.webdav.hostname) try: urn = Urn(remote_path) parent_urn = Urn(urn.parent()) if not self.check(urn.path()) and not self.check( Urn(remote_path, directory=True).path()): raise RemoteResourceNotFound(remote_path) response = BytesIO() url = { 'hostname': self.webdav.hostname, 'root': self.webdav.root, 'path': parent_urn.quote() } options = { 'URL': "{hostname}{root}{path}".format(**url), 'CUSTOMREQUEST': Client.requests['info'], 'HTTPHEADER': self.get_header('info'), 'WRITEDATA': response, 'NOBODY': 0 } request = self.Request(options=options) request.perform() request.close() path = "{root}{path}".format(root=self.webdav.root, path=urn.path()) return parse(response, path) except pycurl.error: raise NotConnection(self.webdav.hostname)
def is_dir(self, remote_path): def parse(response, path): try: response_str = response.getvalue() tree = etree.fromstring(response_str) resps = tree.findall("{DAV:}response") for resp in resps: href = resp.findtext("{DAV:}href") urn = unquote(href) if path[-1] == Urn.separate: if not path == urn: continue else: path_with_sep = "{path}{sep}".format(path=path, sep=Urn.separate) if not path == urn and not path_with_sep == urn: continue type = resp.find(".//{DAV:}resourcetype") if type is None: raise MethodNotSupported(name="is_dir", server=self.webdav.hostname) dir_type = type.find("{DAV:}collection") return True if dir_type is not None else False raise RemoteResourceNotFound(path) except etree.XMLSyntaxError: raise MethodNotSupported(name="is_dir", server=self.webdav.hostname) try: urn = Urn(remote_path) parent_urn = Urn(urn.parent()) if not self.check(urn.path()) and not self.check(Urn(remote_path, directory=True).path()): raise RemoteResourceNotFound(remote_path) response = BytesIO() url = {'hostname': self.webdav.hostname, 'root': self.webdav.root, 'path': parent_urn.quote()} options = { 'URL': "{hostname}{root}{path}".format(**url), 'CUSTOMREQUEST': Client.requests['info'], 'HTTPHEADER': self.get_header('info'), 'WRITEDATA': response, 'NOBODY': 0 } request = self.Request(options=options) request.perform() request.close() path = "{root}{path}".format(root=self.webdav.root, path=urn.path()) return parse(response, path) except pycurl.error: raise NotConnection(self.webdav.hostname)