def getfilelist(self, bucket, offset=0, limit=20, header=None): """ 获取空间中文件列表 @param bucket: string类型,空间名称 @param offset: integer类型,文件列表偏移位置 @param limit: integer类型,返回文件数量 @return ret: 如果http状态码为[200, 204, 206]之一则返回None,否则如果服务器返回json信息则返回dict类型,键值对类型分别为string, unicode string类型,否则返回空的dict @return ResponseInfo: 响应的具体信息,UCloud UFile 服务器返回信息或者网络链接异常 """ if header is None: header = dict() else: _check_dict(header) if 'User-Agent' not in header: header['User-Agent'] = config.get_default('user_agent') param = dict() param['Action'] = 'GetFileList' param['BucketName'] = bucket param['Offset'] = s(str(offset)) param['Limit'] = s(str(limit)) signature = self.__auth.bucket_signature(param) param['Signature'] = signature logger.info('start request the file list of bucket {0}'.format(bucket)) return _bucket_request(UCLOUD_API_URL, param, header)
def describebucket(self, bucket=None, offset=0, limit=10, header=None): """ 获取空间的信息,如果不提供空间名称,则获取所有空间的信息 @param bucketname: string类型, 空间名称 @param offset: integer类型, 起始空间编码,当提供空间名时无效 @param limit: integer类型,获取空间数量,当提供具体空间名时无效 @param header: dict类型,http 请求header,键值对类型分别为string,比如{'User-Agent': 'Google Chrome'} @return ret: 如果http状态码为[200, 204, 206]之一则返回None,否则如果服务器返回json信息则返回dict类型,键值对类型分别为string, unicode string类型,否则返回空的dict @return ResponseInfo: 响应的具体信息,UCloud UFile 服务器返回信息或者网络链接异常 """ if header is None: header = dict() else: _check_dict(header) if 'User-Agent' not in header: header['User-Agent'] = config.get_default('user_agent') param = dict() param['Action'] = 'DescribeBucket' if bucket is not None: param['BucketName'] = bucket param['Offset'] = s(str(offset)) param['Limit'] = s(str(limit)) signature = self.__auth.bucket_signature(param) param['Signature'] = signature logger.info('start request the bucket {0} details'.format(bucket)) return _bucket_request(UCLOUD_API_URL, param, header)
def putfile(self, bucket, key, localfile, header=None): """ upload localfile to bucket as key @param bucket: string类型,上传空间名称 @param key: string 类型,上传文件在空间中的名称 @param localfile: string类型,本地文件名称 @param header: dict类型,http 请求header,键值对类型分别为string,比如{'User-Agent': 'Google Chrome'} @return ret: 如果http状态码为[200, 204, 206]之一则返回None,否则如果服务器返回json信息则返回dict类型,键值对类型分别为string, unicode string类型,否则返回空的dict @return ResponseInfo: 响应的具体信息,UCloud UFile 服务器返回信息或者网络链接异常 """ if header is None: header = dict() else: _check_dict(header) if 'User-Agent' not in header: header['User-Agent'] = config.get_default('user_agent') mime_type = s(Mimetype.from_file(localfile)) file_size = os.path.getsize(localfile) header['Content-Type'] = mime_type authorization = self.authorization('put', bucket, key, header) header['Authorization'] = authorization header['Content-Length'] = file_size url = ufile_put_url(bucket, key) logger.info('start put file {0} to bucket {1} as {2}'.format(localfile, bucket, key)) logger.info('put UFile url: {0}'.format(url)) logger.info('request header:\n{0}'.format(json.dumps(header, indent=4))) return _put_file(url, header, localfile)
def resumeuploadfile(self, retrycount=3, retryinterval=5, bucket=None, key=None, uploadid=None, blocksize=None, etaglist=None, localfile=None, pausepartnumber=None, mime_type=None, header=None): """ 断点续传失败的本地文件分片 可以在调用uploadfile失败后重新续传,也可以通过传递所有需要的参数续传 @param retrycount: integer 类型,分片重传次数 @param retryinterval: integer 类型,同个分片失败重传间隔,单位秒 @param bucket: string类型, 空间名称 @param key: string类型,文件或数据在空间中的名称 @param uploadid: string类型,初始化分片获得的uploadid @param blocksize: integer类型,分片大小 @param etaglist: list类型,元素为已经上传成功的分片的etag @param pausepartnumber: integer类型,第一个失败分片的编号(编号从0开始) @param localfile: string类型,本地文件名称 @param mime_type: string类型,上传数据的MIME类型 @param header: dict类型,http 请求header,键值对类型分别为string,比如{'User-Agent': 'Google Chrome'} @return ret: 如果http状态码为[200, 204, 206]之一则返回None,否则如果服务器返回json信息则返回dict类型,键值对类型分别为string, unicode string类型,否则返回空的dict @return ResponseInfo: 响应的具体信息,UCloud UFile 服务器返回信息或者网络链接异常 """ if localfile: self.__localfile = localfile if blocksize: self.blocksize = blocksize if pausepartnumber: self.pausepartnumber = pausepartnumber if mime_type: self.__mimetype = mime_type else: mime_type = s(Mimetype.from_file(self.__localfile)) with open(self.__localfile, 'rb') as fd: fd.seek(self.pausepartnumber * self.blocksize, os.SEEK_SET) return self.resumeuploadstream(retrycount, retryinterval, bucket, key, uploadid, blocksize, etaglist, fd, pausepartnumber, mime_type, header)
def private_download_url(self, bucket, key, expires=config.get_default('expires'), header=None, internal=False): """ 从私有空间下载文件的url @param bucket: string类型, 空间名称 @param key: string类型,下载数据在空间中的名称 @param expires: integer类型, 下载链接有效时间,单位为秒 @param header: dict类型,http 请求header,键值对类型分别为string,比如{'User-Agent': 'Google Chrome'} @return string, 从私有空间下载文件和数据的url """ if header is None: header = dict() else: _check_dict(header) if 'User-Agent' not in header: header['User-Agent'] = config.get_default('user_agent') if expires is not None: expires += int(time.time()) header['Expires'] = s(str(expires)) signature = self.signature(bucket, key, 'get', header) query = { 'UCloudPublicKey': self._public_key(), 'Expires': str(expires), 'Signature': signature } query_str = urllib.urlencode(query) if internal: return 'http://{0}{1}/{2}?{3}'.format(bucket, config.get_default('download_suffix'), key, query_str) else: return 'http://{0}{1}/{2}?UCloudPublicKey={3}&Expires={4}&Signature={5}'.format(bucket, config.get_default('download_suffix'), key, self._public_key(), str(expires), signature)
def list(self, bucket, marker, limit, header=None): """ @param bucket: string类型,上传空间名称 @param marker: string类型,上一次查找返回的位置信息,本次列表起始查找的文件名,默认为空 @param limit: integer类型, 每次列表返回的最大文件个数,服务端限制为1000,最新限制值请参考官方文档 @param header: dict类型,http 请求header,键值对类型分别为string,比如{'User-Agent': 'Google Chrome'} @return ret: 如果http状态码为[200, 204, 206]之一则返回None,否则如果服务器返回json信息则返回dict类型,键值对类型分别为string, unicode string类型,否则返回空的dict @return ResponseInfo: 响应的具体信息,UCloud UFile 服务器返回信息或者网络链接异常 """ if header is None: header = dict() else: _check_dict(header) if 'User-Agent' not in header: header['User-Agent'] = config.get_default('user_agent') mime_type = s(Mimetype.from_file(localfile)) file_size = os.path.getsize(localfile) header['Content-Type'] = mime_type authorization = self.authorization('put', bucket, key, header) header['Authorization'] = authorization header['Content-Length'] = str(file_size) url = ufile_put_url(bucket, key) logger.info('start put file {0} to bucket {1} as {2}'.format(localfile, bucket, key)) logger.info('put UFile url: {0}'.format(url)) logger.info('request header:\n{0}'.format(json.dumps(header, indent=4))) return _put_file(url, header, localfile)
def putfile(self, bucket, key, localfile, header=None): """ upload localfile to bucket as key @param bucket: string类型,上传空间名称 @param key: string 类型,上传文件在空间中的名称 @param localfile: string类型,本地文件名称 @param header: dict类型,http 请求header,键值对类型分别为string,比如{'User-Agent': 'Google Chrome'} @return ret: 如果http状态码为[200, 204, 206]之一则返回None,否则如果服务器返回json信息则返回dict类型,键值对类型分别为string, unicode string类型,否则返回空的dict @return ResponseInfo: 响应的具体信息,UCloud UFile 服务器返回信息或者网络链接异常 """ if header is None: header = dict() else: _check_dict(header) if 'User-Agent' not in header: header['User-Agent'] = config.get_default('user_agent') mime_type = s(Mimetype.from_file(localfile)) file_size = os.path.getsize(localfile) header['Content-Type'] = mime_type authorization = self.authorization('put', bucket, key, header) header['Authorization'] = authorization header['Content-Length'] = file_size url = ufile_put_url(bucket, key) logger.info('start put file {0} to bucket {1} as {2}'.format( localfile, bucket, key)) logger.info('put UFile url: {0}'.format(url)) logger.info('request header:\n{0}'.format(json.dumps(header, indent=4))) return _put_file(url, header, localfile)
def getfilelist(self, bucket, prefix=None, marker=None, limit=None, header=None): """ 获取bucket下的文件列表 @param bucket: string 类型,空间名称 @param prefix: string 类型,文件前缀, 默认为空字符串 @param marker: string 类型,文件列表起始位置, 默认为空字符串 @param limit: integer 类型,文件列表数目, 默认为20 @param header: dict类型,http 请求header,键值对类型分别为string,比如{'User-Agent': 'Google Chrome'} @return ret: 如果http状态码为[200, 204, 206]之一则返回None,否则如果服务器返回json信息则返回dict类型,键值对类型分别为string, unicode string类型,否则返回空的dict @return ResponseInfo: 响应的具体信息,UCloud UFile 服务器返回信息或者网络链接异常 """ if header is None: header = dict() else: _check_dict(header) if 'User-Agent' not in header: header['User-Agent'] = config.get_default('user_agent') header['Content-Length'] = 0 authorization = self.authorization('get', bucket, '', header) header['Authorization'] = authorization param = dict() if marker is not None and (isinstance(marker, str) or isinstance(marker, unicode)): param['marker'] = s(marker) if prefix is not None and (isinstance(prefix, str) or isinstance(prefix, unicode)): param['prefix'] = s(prefix) if limit is not None and isinstance(limit, int): param['limit'] = s(str(limit)) info_message = ''.join([ 'start get file list from bucket {0}'.format(bucket), '' if marker is None else ', marker: {0}'.format( marker if isinstance(marker, str) else marker.encode('utf-8')), '' if limit is None else ', limit: {0}'.format(limit), '' if prefix is None else ', prefix: {0}'.format(prefix) ]) logger.info(info_message) url = ufile_getfilelist_url(bucket) return _getfilelist(url, header, param)
def uploadfile(self, bucket, key, localfile, retrycount=3, retryinterval=5, header=None): """ 分片上传本地文件到空间 @param bucket: string类型,空间名称 @param key: string类型,文件在空间中的名称 @param localfile: string 类型,本地文件名称 @param retrycount: integer 类型,分片重传次数 @param retryinterval: integer 类型,同个分片失败重传间隔,单位秒 @param header: dict类型,http 请求header,键值对类型分别为string,比如{'User-Agent': 'Google Chrome'} @return ret: 如果http状态码为[200, 204, 206]之一则返回None,否则如果服务器返回json信息则返回dict类型,键值对类型分别为string, unicode string类型,否则返回空的dict @return ResponseInfo: 响应的具体信息,UCloud UFile 服务器返回信息或者网络链接异常 """ self.__localfile = localfile mime_type = s(Mimetype.from_file(self.__localfile)) with open(localfile, 'rb') as fd: return self.uploadstream(bucket, key, fd, retrycount, retryinterval, mime_type, header)
def postfile(self, bucket, key, localfile, header=None): """ 表单上传文件到UFile空间 @param bucket: string类型,上传空间名称 @param key: string 类型,上传文件在空间中的名称 @param localfile: string类型,本地文件名称 @param header: dict类型,http 请求header,键值对类型分别为string,比如{'User-Agent': 'Google Chrome'} @return ret: 如果http状态码为[200, 204, 206]之一则返回None,否则如果服务器返回json信息则返回dict类型,键值对类型分别为string, unicode string类型,否则返回空的dict @return ResponseInfo: 响应的具体信息,UCloud UFile 服务器返回信息或者网络链接异常 """ if header is None: header = dict() _check_dict(header) if 'User-Agent' not in header: header['User-Agent'] = config.get_default('user_agent') mime_type = s(Mimetype.from_file(localfile)) # update the request header content-type boundary = self.__make_boundary() header['Content-Type'] = 'multipart/form-data; boundary={0}'.format( boundary) # form fields authorization = self.authorization('post', bucket, key, header, mime_type) fields = dict() fields['FileName'] = key fields['Authorization'] = authorization with open(localfile, 'rb') as stream: postdata = self.__make_postbody(boundary, fields, stream, mime_type, localfile) # update the request header content-length header['Content-Length'] = str(len(postdata)) # post url url = ufile_post_url(bucket) # start post file logger.info('start post file {0} to bucket {1} as {2}'.format( localfile, bucket, key)) logger.info('post url is {0}'.format(url)) return _post_file(url, header, postdata)
def postfile(self, bucket, key, localfile, header=None): """ 表单上传文件到UFile空间 @param bucket: string类型,上传空间名称 @param key: string 类型,上传文件在空间中的名称 @param localfile: string类型,本地文件名称 @param header: dict类型,http 请求header,键值对类型分别为string,比如{'User-Agent': 'Google Chrome'} @return ret: 如果http状态码为[200, 204, 206]之一则返回None,否则如果服务器返回json信息则返回dict类型,键值对类型分别为string, unicode string类型,否则返回空的dict @return ResponseInfo: 响应的具体信息,UCloud UFile 服务器返回信息或者网络链接异常 """ if header is None: header = dict() _check_dict(header) if "User-Agent" not in header: header["User-Agent"] = config.get_default("user_agent") mime_type = s(Mimetype.from_file(localfile)) # update the request header content-type boundary = self.__make_boundary() header["Content-Type"] = "multipart/form-data; boundary={0}".format(boundary) # form fields authorization = self.authorization("post", bucket, key, header, mime_type) fields = dict() fields["FileName"] = key fields["Authorization"] = authorization with open(localfile, "rb") as stream: postdata = self.__make_postbody(boundary, fields, stream, mime_type, localfile) # update the request header content-length header["Content-Length"] = len(postdata) # post url url = ufile_post_url(bucket) # start post file logger.info("start post file {0} to bucket {1} as {2}".format(localfile, bucket, key)) logger.info("post url is {0}".format(url)) return _post_file(url, header, postdata)
def uploadhit(self, bucket, key, localfile, header=None): """ 尝试秒传文件到UFile空间 @param bucket: string类型,上传空间名称 @param key: string 类型,上传文件在空间中的名称 @param localfile: string类型,本地文件名称 @param header: dict类型,http 请求header,键值对类型分别为string,比如{'User-Agent': 'Google Chrome'} @return ret: 如果http状态码为[200, 204, 206]之一则返回None,否则如果服务器返回json信息则返回dict类型,键值对类型分别为string, unicode string类型,否则返回空的dict @return ResponseInfo: 响应的具体信息,UCloud UFile 服务器返回信息或者网络链接异常 """ if header is None: header = dict() _check_dict(header) if 'User-Agent' not in header: header['User-Agent'] = config.get_default('user_agent') filesize = os.path.getsize(localfile) fileetags = file_etag(localfile, BLOCKSIZE) mimetype = s(Mimetype.from_file(localfile)) # update request header header['Content-Type'] = mimetype header['Content-Length'] = 0 authorization = self.authorization('post', bucket, key, header) header['Authorization'] = authorization # parameter params = {'Hash': fileetags, 'FileName': key, 'FileSize': filesize} url = ufile_uploadhit_url(bucket) logger.info('start upload hit localfile {0} as {1} in bucket {2}'.format(localfile, key, bucket)) logger.info('request url: {0}'.format(url)) return _uploadhit_file(url, header, params)
def uploadstream(self, bucket, key, stream, retrycount=3, retryinterval=5, mime_type=None, header=None): """ 分片上传二进制数据流到UFile空间 @param bucket: 空间名称 @param key: 上传数据在空间中的名称 @param stream: file-like 对象或者二进制数据流 @param mime_type: 上传数据的MIME类型 @param retrycount: integer 类型,分片重传次数 @param retryinterval: integer 类型,同个分片失败重传间隔,单位秒 @param header: dict类型,http 请求header,键值对类型分别为string,比如{'User-Agent': 'Google Chrome'} @return ret: 如果http状态码为[200, 204, 206]之一则返回None,否则如果服务器返回json信息则返回dict类型,键值对类型分别为string, unicode string类型,否则返回空的dict @return ResponseInfo: 响应的具体信息,UCloud UFile 服务器返回信息或者网络链接异常 """ self.__bucket = bucket self.__key = key self.etaglist = [] self.uploadid = None self.blocksize = None self.__header = header self.__stream = stream self.pausepartnumber = 0 if self.__header is None: self.__header = dict() else: _check_dict(self.__header) if 'User-Agent' not in self.__header: self.__header['User-Agent'] = config.get_default('user_agent') # initial sharding request ret, resp = self.__initialsharding() if resp.ok(): self.uploadid = ret.get('UploadId') self.blocksize = ret.get('BlkSize') logger.info('multipart upload id: {0}'.format(self.uploadid)) else: logger.error('multipar upload init failed. error message: {0}'.format(resp.error)) return ret, resp # mulitple sharding upload if mime_type is None: if hasattr(self.__stream, 'seek') and hasattr(self.__stream, 'read'): self.__mimetype = s(Mimetype.from_buffer(self.__stream.read(1024))) self.__stream.seek(0, os.SEEK_SET) else: self.__mimetype = 'application/octec-stream' else: self.__mimetype = mime_type self.__header['Content-Type'] = self.__mimetype authorization = self.authorization('put', self.__bucket, self.__key, self.__header) self.__header['Authorization'] = authorization for data in _file_iter(self.__stream, self.blocksize): url = shardingupload_url(self.__bucket, self.__key, self.uploadid, self.pausepartnumber) ret = None resp = None for index in range(retrycount): logger.info('try {0} time sharding upload sharding {1}'.format(index + 1, self.pausepartnumber)) logger.info('sharding url:{0}'.format(url)) ret, resp = _shardingupload(url, data, self.__header) if not resp.ok(): logger.error('failed {0} time when upload sharding {1}.error message: {2}, uploadid: {3}'.format(index + 1, self.pausepartnumber, resp.error, self.uploadid)) if index < retrycount - 1: time.sleep(retryinterval) else: break if not resp.ok(): logger.error('upload sharding {0} failed. uploadid: {1}'.format(self.pausepartnumber, self.uploadid)) return ret, resp logger.info('upload sharding {0} succeed.etag:{1}, uploadid: {2}'.format(self.pausepartnumber, resp.etag, self.uploadid)) self.pausepartnumber += 1 self.etaglist.append(resp.etag) logger.info('start finish sharding request.') ret, resp = self.__finishupload() if not resp.ok(): logger.error('multipart upload failed. uploadid:{0}, pausepartnumber: {1}, key: {2} FAIL!!!'.format(self.uploadid, self.pausepartnumber, self.__key)) else: logger.info('mulitpart upload succeed. uploadid: {0}, key: {1} SUCCEED!!!'.format(self.uploadid, self.__key)) return ret, resp
def uploadstream(self, bucket, key, stream, retrycount=3, retryinterval=5, mime_type=None, header=None): """ 分片上传二进制数据流到UFile空间 @param bucket: 空间名称 @param key: 上传数据在空间中的名称 @param stream: file-like 对象或者二进制数据流 @param mime_type: 上传数据的MIME类型 @param retrycount: integer 类型,分片重传次数 @param retryinterval: integer 类型,同个分片失败重传间隔,单位秒 @param header: dict类型,http 请求header,键值对类型分别为string,比如{'User-Agent': 'Google Chrome'} @return ret: 如果http状态码为[200, 204, 206]之一则返回None,否则如果服务器返回json信息则返回dict类型,键值对类型分别为string, unicode string类型,否则返回空的dict @return ResponseInfo: 响应的具体信息,UCloud UFile 服务器返回信息或者网络链接异常 """ self.__bucket = bucket self.__key = key self.etaglist = [] self.uploadid = None self.blocksize = None self.__header = header self.__stream = stream self.pausepartnumber = 0 if self.__header is None: self.__header = dict() else: _check_dict(self.__header) if 'User-Agent' not in self.__header: self.__header['User-Agent'] = config.get_default('user_agent') # initial sharding request ret, resp = self.__initialsharding() if resp.ok(): self.uploadid = ret.get('UploadId') self.blocksize = ret.get('BlkSize') logger.info('multipart upload id: {0}'.format(self.uploadid)) else: logger.error( 'multipar upload init failed. error message: {0}'.format( resp.error)) return ret, resp # mulitple sharding upload if mime_type is None: if hasattr(self.__stream, 'seek') and hasattr( self.__stream, 'read'): self.__mimetype = s( Mimetype.from_buffer(self.__stream.read(1024))) self.__stream.seek(0, os.SEEK_SET) else: self.__mimetype = 'application/octec-stream' else: self.__mimetype = mime_type self.__header['Content-Type'] = self.__mimetype authorization = self.authorization('put', self.__bucket, self.__key, self.__header) self.__header['Authorization'] = authorization for data in _file_iter(self.__stream, self.blocksize): url = shardingupload_url(self.__bucket, self.__key, self.uploadid, self.pausepartnumber) ret = None resp = None for index in range(retrycount): logger.info('try {0} time sharding upload sharding {1}'.format( index + 1, self.pausepartnumber)) logger.info('sharding url:{0}'.format(url)) ret, resp = _shardingupload(url, data, self.__header) if not resp.ok(): logger.error( 'failed {0} time when upload sharding {1}.error message: {2}, uploadid: {3}' .format(index + 1, self.pausepartnumber, resp.error, self.uploadid)) if index < retrycount - 1: time.sleep(retryinterval) else: break if not resp.ok(): logger.error( 'upload sharding {0} failed. uploadid: {1}'.format( self.pausepartnumber, self.uploadid)) return ret, resp logger.info( 'upload sharding {0} succeed.etag:{1}, uploadid: {2}'.format( self.pausepartnumber, resp.etag, self.uploadid)) self.pausepartnumber += 1 self.etaglist.append(resp.etag) logger.info('start finish sharding request.') ret, resp = self.__finishupload() if not resp.ok(): logger.error( 'multipart upload failed. uploadid:{0}, pausepartnumber: {1}, key: {2} FAIL!!!' .format(self.uploadid, self.pausepartnumber, self.__key)) else: logger.info( 'mulitpart upload succeed. uploadid: {0}, key: {1} SUCCEED!!!'. format(self.uploadid, self.__key)) return ret, resp