2013-05-09 15:05:42 ztejiagn 阅读数 2680

http://www.cnblogs.com/lxguidu/archive/2013/04/25/3042137.html

1、背景知识

OpenStack Object Storage (Swift) 是用来创建冗余的、可扩展的对象存储(引擎)的开源软件。 swift使用标准化的服务器存储 PB 级的访问数据。它并不是文件系统或者实时的数据存储系统 ,而是一个用于存储永久类型的静态数据的长期存储系统 ,这些数据可以检索、调整、必要时进行更新。最适合存储的数据类型的首要例子是虚拟机镜像,图片存储,邮件存储,存档备份。因为没有中心单元或者主控结点,swift提供了更强的扩展性、冗余和持久性。

OpenStack Object Storage (Swift)使用RESTful API对外提供服务,通过HTTP协议来进行数据间的交互,数据存放在request中。Swift支持单个无文件最大5G,大于5G的文件在客户端切分上传,并上传manifest文件。

 

图 1-1 SWIFT数据交互

 

2、API使用描述

1)获取token

接口名称:

获取一个token ID

接口定义:

curl -X POST -d '
{"auth":
        {"tenantName": “{租户名}”,
         "passwordCredentials": {
            "username": “{用户名}”,
            "password": “{用户密码}”}
        }
 }' 
-H "Content-type: application/json" http://localhost:35357/v2.0/tokens | python -mjson.tool
 

传入参数定义:

{"tenantName": “{租户名}”,
     "passwordCredentials": {
     "username": “{用户名}”,
     "password": “{用户密码}”}
}
 

返回结果:

返回的结果比较冗长,请自己在实验环境192.168.0.191上操作,并观察。而需要注意的是其中token的结果:
"token": {
     "expires": "2012-09-27T13:41:15Z", 
            "id": "d8444bd1ab8140ceb136d748eef86647", 
            "tenant": {
                "description": null, 
                "enabled": true, 
                "id": "e8b18580e5b44cb79b10bd0f7a03bbdc", 
                "name": "admin"
            }
        }
在以下的接口操作中,都需要从该token中获取它的id,以及其对应租户(tenant)的id。

协议:

http

示例:

curl -X POST -d '{"auth": {"tenantName": "admin", "passwordCredentials":{"username": "admin", "password": "pengchao"}}}' -H "Content-type: application/json" http://192.168.0.191:35357/v2.0/tokens | python -mjson.tool

 

2)容器列表

接口名称:

获取容器列表

接口定义:

curl -s http://localhost:8080/v1/AUTH_{Tenant_id} \
     -X GET \
     -H "X-Auth-Token: { Token_id}"
 

传入参数定义:

Tenant_id:租户id
Token_id:租户对应的token的id

返回结果:

 

协议:

http

示例:

curl -s http://192.168.0.191:8080/v1/AUTH_e8b18580e5b44cb79b10bd0f7a03bbdc -X GET -H "X-Auth-Token: 22ec6a37ed6b4b23a435e6b9050f21a4"

 

3)创建容器

接口名称:

创建容器

接口定义:

curl -s http://localhost:8080/v1/AUTH_{Tenant_id}/{Container_name} \
     -X PUT \
     -H "X-Auth-Token: { Token_id}"
 

传入参数定义:

Tenant_id:租户id
Container_name: 所创建的容器名称
Token_id:租户对应的token的id

返回结果:

如果创建成功,返回“201 Created”

协议:

http

示例:

curl -s http://192.168.0.191:8080/v1/AUTH_e8b18580e5b44cb79b10bd0f7a03bbdc -X GET -H "X-Auth-Token: 22ec6a37ed6b4b23a435e6b9050f21a4"

 

4)删除容器

接口名称:

删除容器

接口定义:

curl -s http://localhost:8080/v1/AUTH_{Tenant_id}/{Container_name} \
     -X DELETE \
     -H "X-Auth-Token: { Token_id}"

传入参数定义:

Tenant_id:租户id
Container_name: 所删除的容器名称
Token_id:租户对应的token的id

返回结果:

如果删除成功,什么也没返回。可以使用列出容器的api验证。

协议:

http

示例:

curl -s http://192.168.0.191:8080/v1/AUTH_e8b18580e5b44cb79b10bd0f7a03bbdc/my_container -X DELETE -H "X-Auth-Token: 22ec6a37ed6b4b23a435e6b9050f21a4"

 

5)列出对象

接口名称:

列出容器对象

接口定义:

curl -s http://localhost:8080/v1/AUTH_{Tenant_id}/{Container_name}[?parm=value] \
     -X GET \
     -H "X-Auth-Token: { Token_id}"

传入参数定义:

Tenant_id:租户id
Container_name: 容器名称
Token_id:租户对应的token的id

返回结果:

 

协议:

http

示例:

curl -s http192.168.0.191:8080/v1/AUTH_AUTH_e8b18580e5b44cb79b10bd0f7a03bbdc/my_container?format=json -X GET -H "X-Auth-Token: 22ec6a37ed6b4b23a435e6b9050f21a4" | python -mjson.tool

 

6)创建对象

接口名称:

创建对象

接口定义:

curl –X PUT -i \
    -H "X-Auth-Token: { Token_id}" \
    -T {obj_path} \
    http://localhost:8080/v1/AUTH_{Tenant_id}/{Container_name}/{obj_name}

传入参数定义:

Tenant_id:租户id
Obj_path:对象的完整路径
obj_name:对象名称
Container_name: 容器名称
Token_id:租户对应的token的id

返回结果:

<html>
 <head>
  <title>201 Created</title>
 </head>
 <body>
  <h1>201 Created</h1>
  <br /><br />
 </body>
</html>

协议:

http

示例:

curl -X PUT -i -H "X-Auth-Token: 22ec6a37ed6b4b23a435e6b9050f21a4" -T ufw.log  http://192.168.0.191:8080/v1/AUTH_e8b18580e5b44cb79b10bd0f7a03bbdc/my_container/ufw.log

 

7)删除对象

接口名称:

删除对象

接口定义:

curl -s http://localhost:8080/v1/AUTH_{Tenant_id}/{Container_id}/{object_name} \
     -X DELETE \
     -H "X-Auth-Token: { Token_id}"

传入参数定义:

Tenant_id:租户id
Obj_name:对象名称
Container_name: 所删除的容器名称
Token_id:租户对应的token的id

返回结果:

无返回

协议:

http

示例:

curl -s http://192.168.0.191:8080/v1/AUTH_e8b18580e5b44cb79b10bd0f7a03bbdc/my_container/history24 -X DELETE -H "X-Auth-Token: 22ec6a37ed6b4b23a435e6b9050f21a4"

 

3、实例:使用Python实现

3.1、前提条件

由于数据是存放在request中,为了方便,先构造request,使用python(urllib2)代码实现如下:

@param:server_api  根据需要定义的rest url

@param:autho_token 管理员token

@param:send_data 需要发送的数据

@param:method 定义的方法【GET、PUT、DELETE、POST】,默认是POST

def get_server_request(server_api=None, auth_token=None, send_data=None, method=None):
    if not server_api:
        return None
 
    server_request = urllib2.Request(server_api)
    if not server_request:
        return None
 
    server_request.add_header('Content-Type', 'application/json;charset=utf8')
    server_request.add_header('Accept', 'application/json')
    server_request.add_header('User-Agent', 'python-mikeyp')
    if auth_token:
        server_request.add_header('X-Auth-Token', auth_token)
    if send_data:
        server_request.add_data(send_data)
    if method:
        server_request.get_method = lambda: method
 
    return server_request

 

1)获取keystone认证,进行任何CURD操作,都需要从keystone中获取管理员的租户ID和管理员的token,用Python代码实现如下:

@param:user_name 管理员

@param:password 管理员密码

@param:tenant_name 管理员对应的租户名称

def get_keystone_token(user_name=None, password=None, tenant_name=None):
    server_api = get_Keystone_Endpoint() + 'tokens'
 
    send_data = None
    if user_name and password and tenant_name:
        send_data = {'auth': {'tenantName': tenant_name, 'passwordCredentials': \
                           {'username': user_name, 'password': password}}}
    if not send_data:
        return None
 
    server_request = get_server_request(server_api, None, json.dumps(send_data), None)
    if not server_request:
        return None
 
    try:
        server_response = urllib2.urlopen(server_request)
        receiver_data = server_response.read()
 
        if receiver_data:
            data = json.loads(receiver_data)
            token = data['access']['token']['id']
            tenant_id = data['access']['token']['tenant']['id']
            return (tenant_id, token)
        else:
            return None
    except Exception:
        return None

 

3.2、主要功能实现

以下的代码都能单独使用,实现的关键在于对request操作,实现如下:

server_response = urllib2.urlopen(server_request)

1)列出容器

           

'''列出swift容器列表

@param:

@type:

@return:"count","bytes","name"

@rtype:json

'''

def Container_list():
    server_api = None
    if tenant_id:
        server_api = untils.get_Swift_Endpoint() + tenant_id
    if not server_api:
        api_logger.error('Container_list server_api: %s.' % server_api)
        return untils.rest_result()
 
    try:
        server_request = untils.get_server_request(server_api, token)
        api_logger.info('Container_list server_request: %s.' % server_request)
        if not server_request:
            return untils.rest_result()
        server_response = urllib2.urlopen(server_request)
        api_logger.info('Container_list server_response: %s.' % server_response)
 
        receiver_data = server_response.read()
        if receiver_data:
            data = json.loads(receiver_data)
            con_list = []
            for d in data:
                con_list.append(d['name'])
            return con_list
        return untils.rest_result(True, False)
    except Exception:
        api_logger.critical('Container_list function caught an exception.')
        return untils.rest_result(False, True)

2)创建容器                          

'''创建一个容器

@param:

@type:

@return:"count","bytes","name"

@rtype:json

'''

def Container_create(name=None):
    server_api = None
    if tenant_id:
        server_api = untils.get_Swift_Endpoint() + tenant_id + "/" + name
    if not server_api:
        api_logger.error('Container_create server_api: %s.' % server_api)
        return untils.rest_result()
 
    try:
        server_request = untils.get_server_request(server_api, token, None, "PUT")
        api_logger.info('Container_create server_request: %s.' % server_request)
        if not server_request:
            return untils.rest_result()
        server_response = urllib2.urlopen(server_request)
        api_logger.info('Container_create server_response: %s.' % server_response)
 
        receiver_data = server_response.read()
        if receiver_data:
            data = json.dumps(receiver_data)
            return untils.rest_result(True, False, data)
        return untils.rest_result(True, False)
    except Exception:
        api_logger.critical('Container_create function caught an exception.')
        return untils.rest_result(False, True)

3)删除容器

'''删除一个容器

@param:

@type:

@return:"count","bytes","name"

@rtype:json

'''

def Container_delete(con_name=None):
    if con_name not in Container_list():
        return untils.rest_result()
    obj_list= Object_list(con_name)[0]
    if obj_list:
        api_logger.info("the contaniner is not empty!")
        for obj in obj_list:
            Object_delete(con_name,obj)
 
    server_api = None
    if tenant_id:
        server_api = untils.get_Swift_Endpoint() + tenant_id + "/" + con_name
    if not server_api:
        api_logger.error('Container_delete server_api: %s.' % server_api)
        return untils.rest_result()
 
    try:
        server_request = untils.get_server_request(server_api, token, None, "DELETE")
        api_logger.info('Container_delete server_request: %s.' % server_request)
        if not server_request:
            return untils.rest_result()
        server_response = urllib2.urlopen(server_request)
        api_logger.info('Container_delete server_response: %s.' % server_response)
 
        receiver_data = server_response.read()
        if receiver_data:
            data = json.dumps(receiver_data)
            return untils.rest_result(True, False, data)
        return untils.rest_result(True, False)
    except Exception:
        api_logger.critical('Container_delete function caught an exception.')
        return untils.rest_result(False, True)

4)列出对象

'''列出swift某容器的对象列表

@param container_name:容器名称

@type:char

@return:"bytes","last_modified","hash","name","content_type"

@rtype:json

'''

def Object_list(container_name=None):
    server_api = None
    if tenant_id:
        server_api = untils.get_Swift_Endpoint() + tenant_id + "/" + container_name
    if not server_api:
        api_logger.error('Object_list server_api: %s.' % server_api)
        return untils.rest_result()
 
    try:
        server_request = untils.get_server_request(server_api, token)
        api_logger.info('Object_list server_request: %s.' % server_request)
        if not server_request:
            return untils.rest_result()
        server_response = urllib2.urlopen(server_request)
        api_logger.info('Object_list server_response: %s.' % server_response)
 
        receiver_data = server_response.read()
        if receiver_data:
            data = json.loads(receiver_data)
            c_l = []
            for d in data:
                c_l.append(d['name'])
            return untils.rest_result(True, False, c_l)
        return untils.rest_result(True, False)
    except Exception:
        api_logger.critical('Object_list function caught an exception.')
        return untils.rest_result(False, True)

5)上传对象

'''在一个容器内创建、上传一个对象

@param container_name:容器名称

@param file_name:对象名称

@type:char

@return:

@rtype:json

'''

def Object_upload(container_name=None, obj_path=None, obj_name=None):
    send_data = None
    obj_full_path = os.path.join(obj_path, obj_name)
    with open(obj_full_path) as obj:
        send_data = json.dumps(obj.read())
 
    server_api = None
    if tenant_id:
        server_api = untils.get_Swift_Endpoint() + tenant_id + "/" + container_name + "/" + obj_name
    if not server_api:
        api_logger.error('Object_upload server_api: %s.' % server_api)
        return untils.rest_result()
 
    try:
        server_request = untils.get_server_request(server_api, token, send_data, 'PUT')
        api_logger.info('Object_upload server_request: %s.' % server_request)
        if not server_request:
            return untils.rest_result()
        server_response = urllib2.urlopen(server_request)
        api_logger.info('Object_upload server_response: %s.' % server_response)
 
        receiver_data = server_response.read().strip()
        if receiver_data:
            data = json.dumps(receiver_data)
            return untils.rest_result(True, False, data)
        return untils.rest_result(True, False)        
    except Exception:
        api_logger.critical('Object_upload function caught an exception.')
        return untils.rest_result(False, True)

6)下载对象

'''从容器下载一个对象

@param container_name:容器名称

@param file_name:对象名称

@type:char

@return:

@rtype:json

'''

def Object_download(container_name=None, obj_path=None, obj_name=None):
    server_api = None
    if tenant_id:
        server_api = untils.get_Swift_Endpoint() + tenant_id + "/" + container_name + "/" + obj_name
    if not server_api:
        api_logger.error('Object_download server_api: %s.' % server_api)
        return untils.rest_result()
 
    try:
        server_request = untils.get_server_request(server_api, token)
        api_logger.info('Object_download server_request: %s.' % server_request)
        if not server_request:
            return untils.rest_result()
        server_response = urllib2.urlopen(server_request)
        api_logger.info('Object_download server_response: %s.' % server_response)
 
        receiver_data = server_response.read()
        if receiver_data:
            obj_full_path = os.path.join(obj_path, obj_name)
            with open(obj_full_path, "wb") as code:
                code.write(receiver_data)
        return untils.rest_result(True, False)
    except Exception:
        api_logger.critical('Object_download function caught an exception.')
        return untils.rest_result(False, True)

7)删除对象

'''从容器删除一个对象

@param container_name:容器名称

@param file_name:对象名称

@type:char

@return:

@rtype:json

'''

def Object_delete(container_name=None, obj_name=None):
    server_api = None
    if tenant_id:
        server_api = untils.get_Swift_Endpoint() + tenant_id + "/" + container_name + "/" + obj_name
    if not server_api:
        api_logger.error('Object_delete server_api: %s.' % server_api)
        return untils.rest_result()
 
    try:
        server_request = untils.get_server_request(server_api, token, None, 'DELETE')
        api_logger.info('Object_delete server_request: %s.' % server_request)
        if not server_request:
            return untils.rest_result()
        server_response = urllib2.urlopen(server_request)
        api_logger.info('Object_delete server_response: %s.' % server_response)
 
        receiver_data = server_response.read()
        if receiver_data:
            data = json.dumps(receiver_data)
            return untils.rest_result(True, False, data)
        return untils.rest_result(True, False)
    except Exception:
        api_logger.critical('Object_delete function caught an exception.')
        return untils.rest_result(False, True)
2018-07-26 07:47:27 weixin_34354173 阅读数 246

一. 将Protocol的方法声明为mutating
Swift的协议不仅可以被class类型实现,也适用于struct和enum, 因为这个原因在写给别人用的协议时需要考虑是否使用mutating来修饰方法,这个关键字修饰方法是为了能在该方法中国修改struct和enum的变量,“所以如果你没在协议方法里写 mutating 的话,别人如果用 struct 或者 enum 来实现这个协议的话,就不能在方法里改变自己的变量了”。
在使用class来实现带有mutating的方法协议,具体实现的方法前面不需要加mutating的修饰。

二. Sequence Swift 的for in 可以用在所有实现了Sequence的类型上,而为了实现Sequence首先需要实现一个IteratorProtocol。

//首先定义一个实现了IteratorProtocol 的class
class ReverseIterator<T>: IteratorProtocol {
    //IteratorProtocol需要指定一个typealias Element
    typealias Element = T
    var array: [Element]
    var currentIndex = 0
    
    init(array: [Element]) {
        self.array = array
        currentIndex = array.count - 1
    }
    
    //提供一个返回Element?的方法 next()
    func next() -> T? {
        if currentIndex < 0{
            return nil
        } else {
            let element = array[currentIndex]
            currentIndex -= 1
            return element
        }
    }
}

//其次需要顶一个一个继承Sequence 的class
struct ReverseSequence<T>: Sequence {
    //和 IteratorProtocol 很类似,不过换成指定一个 typealias
    typealias Iterator = ReverseIterator<T>
    
    var array: [T]
    init(array: [T]) {
        self.array = array
    }
    
    //提供一个返回ReverseIterator的makeIterator
    func makeIterator() -> ReverseIterator<T> {
        return ReverseIterator(array: self.array)
    }
}

复制代码

在如下使用:

 var arr = [10, 11, 12, 13, 14]
 for (i, _) in ReverseSequence.init(array: arr).enumerated() {
            print("Index\(i) is \(arr[i])")
 }
 
复制代码

三. 多元组
在swift中,返回值可以包含多个值。

四. @autoclosure ??
在swift中对闭包的用法可以进行一些简写如

logIfTrue({return 2 > 1})  写成   logIfTrue({2 > 1})
复制代码

autoclosure就是把一句表达式自动的封装成一个闭包如下:

func logIfTrue(_ predicate:@autoclosure () -> Bool) {
   if predicate() {
       print(true)
    }
 }
复制代码

在使用的时候只需要写 logIfTrue(2 > 1),连{}都可以省略。swift会把2 > 1这个表达式自动转换成() -> Bool

在Swift中,有一个非常有用的操作符 ?? 。可以用来快速地对nil进行条件判断,一个对象在使用??的时候,如Int类型,实际上会被封装成一个 () -> Int

func ??<T>(optional: T?, defaultValue: @autoclosure () -> T) -> T {
     switch optional {
     case .Some(let value):
          return value
      case .None:
        return defaultValue()
      }
 }
复制代码

在这里使用了一个autoclosure 包了一个() -> T,没有autoclosure就不需要在??操作符真正取值之前就需要准备一个默认值传入到这个方法中,实际上我们没有用到这个默认值,而会直接返回optional解包后的值,这样就避免了不必要的开销,方法就是将默认值的计算推迟到optional判定为nil之后。这样就可以很优雅的写法处理对optional及默认值的取值了。
@ autoclosure并不支持带有输入参数的写法。

五. @escaping

 func doWorkAsync(block: @escaping ()->()) {
        DispatchQueue.main.async {
            block()
        }
    }
复制代码

在闭包前加上@escaping来标明这个闭包是会逃逸出这个方法的。如果在父类或者协议中定义了一个接受@escaping为参数的方法,那么在协议的实现或子类中,也同样需要加上@escaping,否则会被认为是不同的方法。

六. 字面量表达
swift提供了一组非常有意思的协议,使用字面量来表达特定的类型,那些实现了字面量表达协议的类型,在赋值的时候就可以简单地按照协议方法中定义的规则“无缝对应”地通过赋值的方式将值表达为对应类型,实际开发中用到的字面量协议:

ExpressibleByArrayLiteral
ExpressibleByBooleanLiteral
ExpressibleByDictionaryLiteral
ExpressibleByFloatLiteral
ExpressibleByNilLiteral
ExpressibleByNilLiteral
复制代码

所有的字面量都定义了一个typealias和对应的init方法。

七. 初始方法顺序
与Objc不同的是,Swift的初始方法需要保证类型的所有属性都被初始化完成之后才调用父类的初始化方法。最后如果有需要,对父类的需要改变的属性进行重新赋值。 值得注意的是在swift中可以对let 声明的常量进行赋值。

八. default参数
swift的方法是支持默认参数的,即在声明方法的时候可以给参数一个默认的值,NSLocalizedString就是其中这样使用的例子。

func sayHello1(str1: String = "Hello", str2: String, str3: String) {
    print(str1 + str2 + str3)
}
复制代码

九. AnyClass,元类型和 .self
通过AnyObject.Type这种方法得到的是一个元类型(Meta),A.Type代表的是A类型的类型。

class A {
}

let typeA: A.Type = A.self
复制代码

.self可以用在类型后面取得类型本身,例如我们经常会在register cell的class的时候会用到这个元类型。

十.属性观察
属性观察 (Property Observers) 是 Swift 中一个很特殊的特性,利用属性观察我们可以在当前类型内监视对于属性的设定,并作出一些响应。Swift 中为我们提供了两个属性观察的方法,它们分别是 willSet 和 didSet。

var date: NSDate {
    willSet {
        let d = date
        print("即将将日期从 \(d) 设定至 \(newValue)")
    }
    
    didSet {
        print("已经将日期从 \(oldValue) 设定至 \(date)")
    }
}
复制代码

值得注意的是,计算属性和观察属性是不能共存的。

十一. Optional Map
在swift中可以对Array使用Map的操作,这个方法能对数组中的所有元素应用某一种规则,我们可以在CollectionType(Array遵守了这个协议)的Extension中找到关于这个方法的定义:

extension CollectionType {
    public func map<T>(@noescape transform: 
                    (Self.Generator.Element) -> T) -> [T]
}

复制代码

从上面的代码可以看出swift中支持协议的扩展。而同样地Optional也有一个类似的map:

public enum Optional<T> : _Reflectable, NilLiteralConvertible {
    /// If `self == nil`, returns `nil`.  Otherwise, returns `f(self!)`.
    public func map<U>(@noescape f: (T) -> U) -> U?

}
复制代码

这个方法很方便地对一个optional值做变化和操作,不比进行手动的解包工作。输入会被自动用类似Optinal Binding 的方式进行判断。这些都符合函子(Functor)的概念。

十二. Swift命令行工具
直接使用swift 可以执行.swift的文件,可以通过swift --help,swiftc --help查看,Swift命令行工具的另一个常用的地方就是直接脱离Xcode环境进行编译和生成可执行文件。

swiftc -O test.swift -o test..asm
复制代码

十三. Filter
常见操作是检查一个数组,然后将这个数组中符合一定条件的元素过滤出来并用它们创建一个新的数组

let nums = [2,4,5,6,7,8,9,10]
let filers = nums.filter { $0 % 2 == 0 }
print(filers)
复制代码

swift中Array和Dictionary中的每一个元素可以用$0来简写,通过组合map 和 filter,我们现在可以轻易完成很多数组操作,而不需要引入中间数组。

filter的实现看起来和map很类似:

extension Array {
    func filter(_ isIncluded: (Element) -> Bool) -> [Element] {
        var result: [Element] = []
        for x in self where isIncluded(x) {
            result.append(x)
        }
        return result
    }
}
复制代码

如果只是想要查找数组中是否有满足条件的元素,从性能上讲就大可不必用filter,而是可以使用contains,一般来讲当我们需要所有结果的时候才去使用filter。

十四. reduce
map和filter都作用在数组上,并产生一个新的、修改过的数组,不过有可能你想要把所有新的元素组合成一个新的值。

let total = nums.reduce(0, +)
复制代码

如下是reduce的实现:

extension Array {
    func reduce<Result>(_ initialResult: Result,
                        _ nextPartialResult: (Result, Element) -> Result) -> Result
    {
        var result = initialResult
        for x in self {
            result = nextPartialResult(result, x)
        }
        return result
    }
}
复制代码

十五. 集合类型协议
1. 序列
Sequence协议是集合类型协议的基础,一个序列代表的是一系列具有相同类型的值,遍历一个序列最简单的方式就是for循环。满足Sequence协议十分简单,就是提供一个返回迭代器的makeIterator() 方法,如最开始的例子。 2.集合类型
集合类型 (Collection) 指的是那些稳定的序列,它们能够被多次遍历且保持一致。Collection协议是简历在Sequence之上,除了从Sequence继承了所有的方法,集合还提供了新的功能如count。

转载于:https://juejin.im/post/5b597c72f265da0f51406839

2016-04-18 17:13:39 HHL110120 阅读数 987

转载地址:http://c.biancheng.net/cpp/html/2291.html
互用性是让 Swift 和 Objective-C 相接合的一种特性,使你能够在一种语言编写的文件中使用另一种语言。当你准备开始把 Swift 融入到你的开发流程中时,你应该懂得如何利用互用性来重新定义并提高你写 Cocoa 应用的方案。

互用性很重要的一点就是允许你在写 Swift 代码时使用 Objective-C 的 API 接口。当你导入一个 Objective-C 框架后,你可以使用原生的 Swift 语法实例化它的 Class 并且与之交互。
初始化

为了使用 Swift 实例化 Objective-C 的 Class,你应该使用 Swift 语法调用它的一个初始化器。当 Objective-C 的init方法变化到 Swift,他们用 Swift 初始化语法呈现。“init”前缀被截断当作一个关键字,用来表明该方法是初始化方法。那些以“initWith”开头的init方法,“With”也会被去除。从“init”或者“initWith”中分离出来的这部分方法名首字母变成小写,并且被当做是第一个参数的参数名。其余的每一部分方法名依次变味参数名。这些方法名都在圆括号中被调用。

举个例子,你在使用 Objective-C 时会这样做:

//Objective-C
UITableView *myTableView = [[UITableView alloc]
initWithFrame:CGRectZero style:UITableViewStyleGrouped];

在 Swift 中,你应该这样做:

//Swift
let myTableView: UITableView = UITableView(frame: CGRectZero, style: .Grouped) 

你不需要调用 alloc,Swift 能替你处理。注意,当使用 Swift 风格的初始化函数的时候,“init”不会出现。
你可以在初始化时显式的声明对象的类型,也可以忽略它,Swift 能够正确判断对象的类型。

let myTextField = UITextField(frame: CGRect(0.0, 0.0, 200.0, 40.0)) 

这里的UITableView和UITextField对象和你在 Objective-C 中使用的具有相同的功能。你可以用一样的方式使用他们,包括访问属性或者调用各自的类中的方法。
为了统一和简易,Objective-C 的工厂方法也在 Swift 中映射为方便的初始化方法。这种映射能够让他们使用同样简洁明了的初始化方法。例如,在 Objective-C 中你可能会像下面这样调用一个工厂方法:

UIColor *color = [UIColor colorWithRed:0.5 green:0.0 blue:0.5 alpha:1.0];

在 Swift 中,你应该这样做:

let color = UIColor(red: 0.5, green: 0.0, blue: 0.5, alpha: 1.0) 
访问属性

在 Swift 中访问和设置 Objective-C 对象的属性时,使用点语法:

myTextField.textColor = UIColor.darkGrayColor()
myTextField.text = "Hello world"
if myTextField.editing {
    myTextField.editing = false
}

当 get 或 set 属性时,直接使用属性名称,不需要附加圆括号。注意,darkGrayColor后面附加了一对圆括号,这是因为darkGrayColor是UIColor的一个类方法,不是一个属性。

在 Objective-C 中,一个有返回值的无参数方法可以被作为一个隐式的访问函数,并且可以与访问器使用同样的方法调用。但在 Swift 中不再能够这样做了,只有使用@property关键字声明的属性才会被作为属性引入。
方法

在 Swift 中调用 Objective-C 方法时,使用点语法。

当 Objective-C 方法转换到 Swift 时,Objective-C 的selector的第一部分将会成为方法名并出现在圆括号的前面,而第一个参数将直接在括号中出现,并且没有参数名,而剩下的参数名与参数则一一对应的填入圆括号中。

举个例子,你在使用 Objective-C 时会这样做:

[myTableView insertSubview:mySubview atIndex:2]; 

在 Swift 中,你应该这样做:

myTableView.insertSubview(mySubview, atIndex: 2) 

如果你调用一个无参方法,仍必须在方法名后面加上一对圆括号

myTableView.layoutIfNeeded() 

id 兼容性(id Compatibility)

Swift 包含一个叫做AnyObject的协议类型,表示任意类型的对象,就像 Objective-C 中的id一样。AnyObject协议允许你编写类型安全的 Swift 代码同时维持无类型对象的灵活性。因为AnyObject协议保证了这种安全,Swift 将 id 对象导入为 AnyObject。

举个例子,跟 id 一样,你可以为AnyObject类型的对象分配任何其他类型的对象,你也同样可以为它重新分配其他类型的对象。

var myObject: AnyObject = UITableViewCell()
myObject = NSDate() 

你也可以在调用 Objective-C 方法或者访问属性时不将它转换为具体类的类型。这包括了 Objcive-C 中标记为 @objc 的方法。

let futureDate = myObject.dateByAddingTimeInterval(10)
let timeSinceNow = myObject.timeIntervalSinceNow 

然而,由于直到运行时才知道AnyObject的对象类型,所以有可能在不经意间写出不安全代码。另外,与 Objective-C 不同的是,如果你调用方法或者访问的属性 AnyObject 对象没有声明,将会报运行时错误。比如下面的代码在运行时将会报出一个 unrecognized selector error 错误:

myObject.characterAtIndex(5)
// crash, myObject does't respond to that method 

但是,你可以通过 Swift 的 optinals 特性来排除这个 Objective-C 中常见的错误,当你用AnyObject对象调用一个 Objective-C 方法时,这次调用将会变成一次隐式展开 optional(implicitly unwrapped optional)的行为。你可以通过 optional 特性来决定 AnyObject 类型的对象是否调用该方法,同样的,你可以把这种特性应用在属性上。

举个例子,在下面的代码中,第一和第二行代码将不会被执行因为length属性和characterAtIndex:方法不存在于 NSDate 对象中。myLength常量会被推测成可选的Int类型并且被赋值为nil。同样你可以使用if-let声明来有条件的展开这个方法的返回值,从而判断对象是否能执行这个方法。就像第三行做的一样。

let myLength = myObject.length?
let myChar = myObject.characterAtIndex?(5)
if let fifthCharacter = myObject.characterAtIndex(5) {
    println("Found \(fifthCharacter) at index 5")
}

对于 Swift 中的强制类型转换,从 AnyObject 类型的对象转换成明确的类型并不会保证成功,所以它会返回一个可选的值。而你需通过检查该值的类型来确认转换是否成功。

let userDefaults = NSUserDefaults.standardUserDefaults()
let lastRefreshDate: AnyObject? = userDefaults.objectForKey("LastRefreshDate")
if let date = lastRefreshDate as? NSDate {
    println("\(date.timeIntervalSinceReferenceDate)")
}

当然,如果你能确定这个对象的类型(并且确定不是nil),你可以添加as操作符强制调用。

let myDate = lastRefreshDate as NSDate
let timeInterval = myDate.timeIntervalSinceReferenceDate 
使用nil

在Objective-C中,对象的引用可以是值为NULL的原始指针(同样也是Objective-C中的nil)。而在Swift中,所有的值–包括结构体与对象的引用–都被保证为非空。作为替代,你将这个可以为空的值包装为optional type。当你需要宣告值为空时,你需要使用nil。你可以在Optionals中了解更多。

因为Objective-C不会保证一个对象的值是否非空,Swift在引入Objective-C的API的时候,确保了所有函数的返回类型与参数类型都是optional,在你使用Objective-C的API之前,你应该检查并保证该值非空。 在某些情况下,你可能绝对确认某些Objective-C方法或者属性永远不应该返回一个nil的对象引用。为了让对象在这种情况下更加易用,Swift使用 implicitly unwrapped optionals 方法引入对象, implicitly unwrapped optionals 包含optional 类型的所有安全特性。此外,你可以直接访问对象的值而无需检查nil。当你访问这种类型的变量时, implicitly unwrapped optional 首先检查这个对象的值是否不存在,如果不存在,将会抛出运行时错误。
扩展(Extensions)

Swift 的扩展和 Objective-C 的类别(Category)相似。扩展为原有的类,结构和枚举丰富了功能,包括在 Objective-C 中定义过的。你可以为系统的框架或者你自己的类型增加扩展,只需要导入合适的模块并且保证你在 Objective-C 中使用的类、结构或枚举拥有相同的名字。

举个例子,你可以扩展UIBezierPath类来为它增加一个等边三角形,这个方法只需提供三角形的边长与起点。

extension UIBezierPath {
    convenience init(triangleSideLength: Float, origin: CGPoint) {
        self.init()
        let squareRoot = Float(sqrt(3))
        let altitude = (squareRoot * triangleSideLength) / 2
        moveToPoint(origin)
        addLineToPoint(CGPoint(triangleSideLength, origin.x))
        addLineToPoint(CGPoint(triangleSideLength / 2, altitude))
        closePath()
    }
}

你也可以使用扩展来增加属性(包括类的属性与静态属性)。然而,这些属性必须是通过计算才能获取的,扩展不会为类,结构体,枚举存储属性。下面这个例子为CGRect类增加了一个叫area的属性。

extension CGRect {
    var area: CGFloat {
    return width * height
    }
}
let rect = CGRect(x: 0.0, y: 0.0, width: 10.0, height: 50.0)
let area = rect.area
// area: CGFloat = 500.0

你同样可以使用扩展来为类添加协议而无需增加它的子类。如果这个协议是在 Swift 中被定义的,你可以添加 comformance 到它的结构或枚举中无论它们在 Objective-C 或在 Swift 中被定义。

你不能使用扩展来覆盖 Objective-C 类型中存在的方法与属性。
闭包(Closures)

Objective-C 中的blocks会被自动导入为 Swift 中的闭包。例如,下面是一个 Objective-C 中的 block 变量:

void (^completionBlock)(NSData *, NSError *) = ^(NSData *data, NSError *error) {/* ... */} 

而它在 Swift 中的形式为

let completionBlock: (NSData, NSError) -> Void = {data, error in /* ... */} 

Swift 的闭包与 Objective-C 中的 blocks 能够和睦相处,所以你可以把一个 Swift 闭包传递给一个把 block 作为参数的 Objective-C 函数。Swift 闭包与函数具有互通的类型,所以你甚至可以传递 Swift 函数的名字。
闭包与 blocks 语义上想通但是在一个地方不同:变量是可以直接改变的,而不是像 block 那样会拷贝变量。换句话说,Swift 中变量的默认行为与 Objective-C 中 __block 变量一致。
比较对象

当比较两个 Swift 中的对象时,可以使用两种方式。第一种,使用(==),判断两个对象内容是否相同。第二种,使用(===),判断常量或者变量是否为同一个对象的实例。

Swift 与 Objective-C 一般使用 == 与 === 操作符来做比较。Swift 的 == 操作符为源自 NSObject 的对象提供了默认的实现。在实现 == 操作符时,Swift 调用 NSObject 定义的 isEqual: 方法。

NSObject 类仅仅做了身份的比较,所以你需要在你自己的类中重新实现 isEqual: 方法。因为你可以直接传递 Swift 对象给 Objective-C 的 API,你也应该为这些对象实现自定义的 isEqual: 方法,如果你希望比较两个对象的内容是否相同而不是仅仅比较他们是不是由相同的对象派生。

作为实现比较函数的一部分,确保根据Object comparison实现对象的hash属性。更进一步的说,如果你希望你的类能够作为字典中的键,也需要遵从Hashable协议以及实现hashValues属性。
Swift 类型兼容性

当你定义了一个继承自NSObject或者其他 Objective-C 类的 Swift 类,这些类都能与 Objective-C 无缝连接。所有的步骤都有 Swift 编译器自动完成,如果你从未在 Objective-C 代码中导入 Swift 类,你也不需要担心类型适配问题。另外一种情况,如果你的 Swift 类并不来源自 Objectve-C 类而且你希望能在 Objecive-C 的代码中使用它,你可以使用下面描述的 @objc 属性。

@objc可以让你的 Swift API 在 Objective-C 中使用。换句话说,你可以通过在任何 Swift 方法、类、属性前添加@objc,来使得他们可以在 Objective-C 代码中使用。如果你的类继承自 Objective-C,编译器会自动帮助你完成这一步。编译器还会在所有的变量、方法、属性前加 @objc,如果这个类自己前面加上了@objc关键字。当你使用@IBOutlet,@IBAction,或者是@NSManaged属性时,@objc也会自动加在前面。这个关键字也可以用在 Objetive-C 中的 target-action 设计模式中,例如,NSTimer或者UIButton。

当你在 Objective-C 中使用 Swift API,编译器基本对语句做直接的翻译。例如,Swift API func playSong(name: String)会被解释为- (void)playSong:(NSString )name。然而,有一个例外:当在 Objective-C 中使用 Swift 的初始化函数,编译器会在方法前添加“initWith”并且将原初始化函数的第一个参数首字母大写。例如,这个 Swift 初始化函数init (songName: String, artist: String将被翻译为- (instancetype)initWithSongName:(NSString )songName artist:(NSString *)artist 。

Swift 同时也提供了一个@objc关键字的变体,通过它你可以自定义在 Objectiv-C 中转换的函数名。例如,如果你的 Swift 类的名字包含 Objecytive-C 中不支持的字符,你就可以为 Objective-C 提供一个可供替代的名字。如果你给 Swift 函数提供一个 Objecytive-C 名字,要记得为带参数的函数添加(:)

@objc(Squirrel)
class Белка {
    @objc(initWithName:)
    init (имя: String) { /*...*/ }
    @objc(hideNuts:inTree:)
    func прячьОрехи(Int, вДереве: Дерево) { /*...*/ }
}

当你在 Swift 类中使用@objc(<#name#>)关键字,这个类可以不需要命名空间即可在 Objective-C 中使用。这个关键字在你迁徙 Objecive-C 代码到 Swift 时同样也非常有用。由于归档过的对象存贮了类的名字,你应该使用@objc(<#name#>)来声明与旧的归档过的类相同的名字,这样旧的类才能被新的 Swift 类解档。
Objective-C 选择器(Selectors)

一个 Objective-C 选择器类型指向一个 Objective-C 的方法名。在 Swift 时代,Objective-C 的选择器被Selector结构体替代。你可以通过字符串创建一个选择器,比如let mySelector: Selector = “tappedButton:”。因为字符串能够自动转换为选择器,所以你可以把字符串直接传递给接受选择器的方法。

import UIKit
class MyViewController: UIViewController {
    let myButton = UIButton(frame: CGRect(x: 0, y: 0, width: 100, height: 50))
    init(nibName nibNameOrNil: String!, bundle nibBundleOrNil: NSBundle!) {
        super.init(nibName: nibName, bundle: nibBundle)
        myButton.targetForAction("tappedButton:", withSender: self)
    }
    func tappedButton(sender: UIButton!) {
        println("tapped button")
    }
}

注意: performSelector:方法和相关的调用选择器的方法没有导入到 Swift 中因为它们是不安全的。
如果你的 Swift 类继承自 Objective-C 的类,你的所有方法都可以用作 Objective-C 的选择器。另外,如果你的 Swift 类不是继承自 Objective-C,如果你想要当选择器来使用你就需要在前面添加@objc关键字,详情请看Swift 类型兼容性。

2016-07-19 16:33:28 sinat_27186785 阅读数 0

Restful API使用描述 

使用限制

 Account(账户)   Container(容器)   Object(对象)    metadata(元数据)

  1. 元数据(metadata)的总个数不能大于90个,且所有元数据总大小不能超过4KB
  2. 元数据名字长度不能大于128个字节
  3. 元数据值的长度不能大于256个字节
  4. 对象最大不能超过5G,超过则需要分割后在上传
  5. 对象名字的总长度不能超过1024个字节
  6. 账户名字的总长度不能超过256个字节
  7. 容器名字的总长度不能超过256个字节
  8. 列取账户中容器的时候一次返回容器个数最大为10000个,如果账户中有超过10000个容器的则需要采用分批获取的方式来获取,列取容器中的对象也一样
  9. 账户名、容器名、对象名和元数据都需要是utf-8或者unicode编码
  10. iQiyi内部的Swift已将对象的自动过期功能取消
  11. HTTP请求的头总大小不能超过8KB

获取token

接口名称:

获取一个token ID

接口定义:

curl -X POST -d '
{"auth":
        {"tenantName": “{租户名}”,
         "passwordCredentials": {
            "username": “{用户名}”,
            "password": “{用户密码}”}
        }
 }' 
-H "Content-type: application/json" http://localhost:5000/v2.0/tokens | python -mjson.tool
 

传入参数定义:

{"tenantName": “{租户名}”,
     "passwordCredentials": {
     "username": “{用户名}”,
     "password": “{用户密码}”}
}
 

返回结果:

返回结果很长,token字段如下:
 "token": {
            "expires": "2013-07-20T08:15:57Z", 
            "id": "c38bcd05c19a4ec7b7f8d0c58b110aac", 
            "tenant": {
                "description": null, 
                "enabled": true, 
                "id": "321879173bf44366a76ba34e84d71d00", 
                "name": "service"
            }
    }, 
在以下的接口操作中,都需要从该token中获取它的id,以及其对应租户(tenant)的id。

协议:

http

示例:

keystone: curl -X POST -d '{"auth": {"tenantName": "service", "passwordCredentials":{"username": "root", "password": "passwd"}}}' -H "Content-type: application/json" http://10.23.70.116:35357/v2.0/tokens | python -mjson.tool

 tempauth: curl -k -v -H 'X-Storage-User: vtc:vtc' -H 'X-Storage-Pass: transcode' http://10.121.56.114:8080/auth/v1.0


存储状态查询

接口名称:

存储状态查询

接口定义:

curl -s http://localhost:8080/v1/AUTH_{Tenant_id} \
     -X HEAD \
     -D -\
     -H "X-Auth-Token: { Token_id}"
 

传入参数定义:

Tenant_id:租户id
Token_id:租户对应的token的id

返回结果:

 返回当前租户容器和对象数量

协议:

http

示例:

curl -s http://10.23.70.117:80/v1/AUTH_5a7bfc63f66c4c6cbdb6c744900c3e09 -X HEAD -D - -H "X-Auth-Token: a3301390309943818d35816fefea50c5"


获取容器列表

接口名称:

获取容器列表

接口定义:

curl -s http://localhost:8080/v1/AUTH_{Tenant_id} \
     -X GET \

           -D -\

     -H "X-Auth-Token: { Token_id}"
如果需要指定输出几个容器可以在加上后缀?limit=number
如果需要指定格式,加上后缀?format=json

传入参数定义:

Tenant_id:租户id
Token_id:租户对应的token的id

返回结果:

 返回当前租户下所有的容器

协议:

http

示例:

 curl -s http://10.23.70.116:8080/v1/AUTH_321879173bf44366a76ba34e84d71d00 -X GET -H "X-Auth-Token: 1cb6d6b77ef54274870490b5f1e5e6a3"


创建容器

接口名称:

创建容器

接口定义:

curl -s http://localhost:8080/v1/AUTH_{Tenant_id}/{Container_name} \
     -X PUT \

           -D -\

     -H "X-Auth-Token: { Token_id}"
 

传入参数定义:

Tenant_id:租户id
Container_name: 所创建的容器名称
Token_id:租户对应的token的id

返回结果:

如果创建成功,返回“201 Created”

协议:

http

示例:

curl -s http://10.23.70.116:8080/v1/AUTH_321879173bf44366a76ba34e84d71d00/testcontainer2 -X PUT -H "X-Auth-Token: 1cb6d6b77ef54274870490b5f1e5e6a3"

 查看容器的metadata

接口名称:

查看容器的metadata

接口定义:

curl -i -s http://localhost:8080/v1/AUTH_{Tenant_id}/{Container_name} \
     -X HEAD \

           -D -\

     -H "X-Auth-Token: { Token_id}"

传入参数定义:

Tenant_id:租户id
Container_name: 所删除的容器名称
Token_id:租户对应的token的id

返回结果:

返回container的matadata。

协议:

http

示例:

curl -i -s http://10.23.70.117:80/v1/AUTH_5a7bfc63f66c4c6cbdb6c744900c3e09/codecloud -X HEAD -D - -H "X-Auth-Token: a3301390309943818d35816fefea50c5"


删除容器

接口名称:

删除容器

接口定义:

curl -s http://localhost:8080/v1/AUTH_{Tenant_id}/{Container_name} \
     -X DELETE \
     -D - -H "X-Auth-Token: { Token_id}"

传入参数定义:

Tenant_id:租户id
Container_name: 所删除的容器名称
Token_id:租户对应的token的id

返回结果:

如果删除成功,什么也没返回。可以使用列出容器的api验证。

协议:

http

示例:

curl -s http://10.23.70.116:8080/v1/AUTH_321879173bf44366a76ba34e84d71d00/testcontainer2 -X DELETE -D - -H "X-Auth-Token: 1cb6d6b77ef54274870490b5f1e5e6a3"


列出对象

接口名称:

列出容器对象

接口定义:

curl -s http://localhost:8080/v1/AUTH_{Tenant_id}/{Container_name}[?parm=value] \
     -X GET \
     -D - -H "X-Auth-Token: { Token_id}"

传入参数定义:

Tenant_id:租户id
Container_name: 容器名称
Token_id:租户对应的token的id

返回结果:

 如果容器中的对象超过10000,则默认返回按字母排序的前10000个对象,关于如何返回后面的对象请参考OpenStack Swift官方API

协议:

http

示例:

curl -s http://10.23.70.116:8080/v1/AUTH_321879173bf44366a76ba34e84d71d00/testcontainer -X GET -D - -H "X-Auth-Token: 1cb6d6b77ef54274870490b5f1e5e6a3"


创建对象

接口名称:

创建对象

接口定义:

curl –X PUT -i \
    -D - -H "X-Auth-Token: { Token_id}" \
    -T {obj_path} \
    http://localhost:8080/v1/AUTH_{Tenant_id}/{Container_name}/{obj_name}

传入参数定义:

Tenant_id:租户id
Obj_path:对象的完整路径
obj_name:对象名称
Container_name: 容器名称
Token_id:租户对应的token的id

返回结果:

<html>
 <head>
  <title>201 Created</title>
 </head>
 <body>
  <h1>201 Created</h1>
  <br /><br />
 </body>
</html>

协议:

http

示例:

 curl -s http://10.23.70.116:8080/v1/AUTH_321879173bf44366a76ba34e84d71d00/testcontainer/install.log -T ~/install.log -X PUT -D - -H "X-Auth-Token: 1cb6d6b77ef54274870490b5f1e5e6a3"


删除对象

接口名称:

删除对象

接口定义:

curl -s http://localhost:8080/v1/AUTH_{Tenant_id}/{Container_id}/{object_name} \
     -X DELETE \
     -D - -H "X-Auth-Token: { Token_id}"

传入参数定义:

Tenant_id:租户id
Obj_name:对象名称
Container_name: 所删除的容器名称
Token_id:租户对应的token的id

返回结果:

无返回

协议:

http

示例:

curl -s http://10.23.70.116:8080/v1/AUTH_321879173bf44366a76ba34e84d71d00/testcontainer/install.log -X DELETE -D - -H "X-Auth-Token: 1cb6d6b77ef54274870490b5f1e5e6a3"


下载对象

接口名称:

下载对象

接口定义:

curl -s http://localhost:8080/v1/AUTH_{Tenant_id}/{Container_id}/{object_name} >Dest path\
     -X GET -D -\
     -H "X-Auth-Token: { Token_id}"

传入参数定义:

Tenant_id:租户id
Obj_name:对象名称
Container_name: 所删除的容器名称
Token_id:租户对应的token的id
Dest path:下载到的目标文件的path

返回结果:

无返回

协议:

http

示例:

curl -s http://10.23.70.116:8080/v1/AUTH_321879173bf44366a76ba34e84d71d00/testcontainer/remi-release-6.rpm>~/backup2/remi-release-6.rpm -X GET -H "X-Auth-Token: 1cb6d6b77ef54274870490b5f1e5e6a3"

查看对象metadata

接口名称:

查看对象的metadata

接口定义:

curl -k -i -s http://localhost:8080/v1/AUTH_{Tenant_id}/{Container_id}/{object_name} \
     -X HEAD -D -\
     -H "X-Auth-Token: { Token_id}"

传入参数定义:

Tenant_id:租户id
Obj_name:对象名称
Container_name: 所删除的容器名称
Token_id:租户对应的token的id

返回结果:

在HTTP头中返回对象的metadata,自定义的metadata都带有X-Object-Meta前缀

协议:

http

示例:

curl -k -i -s http://10.23.70.117:80/v1/AUTH_5a7bfc63f66c4c6cbdb6c744900c3e09/codecloud/install.log -X HEAD -D - -H "X-Auth-Token: a3301390309943818d35816fefea50c5"

更新对象metadata

接口名称:

更新对象的metadata,一个对象的所有metadata总大小不能超过4KB,而且metadata个数不能超过90个

接口定义:

curl -k -i -s http://localhost:8080/v1/AUTH_{Tenant_id}/{Container_id}/{object_name} \
     -X POST \
     -H "X-Object-Meta-metadata_name:new_value" \
     -H "X-Auth-Token: { Token_id}"

传入参数定义:

Tenant_id:租户id
Obj_name:对象名称
Container_name: 所删除的容器名称
Token_id:租户对应的token的id

返回结果:

返回202,表示accepted

协议:

http

示例:

curl -k -i -s http://10.23.70.117:80/v1/AUTH_5a7bfc63f66c4c6cbdb6c744900c3e09/codecloud/install.log -H "X-Timestamp:1375243435.75728" -X POST -H "X-Auth-Token: a3301390309943818d35816fefea50c5"

Command的使用

swift提供的命令行接口进行操作。

 command function   example
 stat [container] [object]  获取容器或者对象的状态信息  swift -V 2 -A http://10.23.70.116:5000/v2.0 -U service:root -K passwd stat
 list [options] [container]  获取容器的对象列表  swift -V 2 -A http://10.23.70.116:5000/v2.0 -U service:root -K passwd list codecloud
 upload [options] container file_or_directory [file_or_directory] [...]  上传对象到指定容器  swift -V 2 -A http://10.23.70.116:5000/v2.0 -U service:root -K passwd upload codecloud install.log
 post [options] [container] [object] 对容器,账号和对象的metadata进行修改,如果没有,就会创建一个新容器。    swift -V 2 -A http://10.23.70.116:5000/v2.0 -U service:root -K passwd post codecloudnew
 download --all OR download container [options] [object] [object]  下载对象

 swift -V 2 -A http://10.23.70.116:5000/v2.0 -U service:root -K passwd downlaod codecloud  install.log

 delete [options] --all OR delete container [options] [object] [object] ...  删除对象  swift -V 2 -A http://10.23.70.116:5000/v2.0 -U service:root -K passwd delete codecloud install.log

关于Api更多的细节参考:http://docs.openstack.org/api/openstack-object-storage/1.0/content/

设置匿名读取或者put某个container和下面的object

接口名称:

匿名读取container及其下面的object

接口定义:

curl -k -i -s http://localhost:8080/v1/AUTH_{Tenant_id}/{Container_id}/\
     -X PUT \
     -H "X-Container-Read: .r:*"\

           -H "X-Container-Write: .r:*"\

     -H "X-Auth-Token: { Token_id}"

传入参数定义:

Tenant_id:租户id
Container_name: 所删除的容器名称
Token_id:租户对应的token的id

返回结果:

返回201,表示成功

协议:

http

示例:

curl -s http://10.23.70.127:8080/v1/AUTH_f02c22db84c54525927353bab5d36b38/containertest2 -X PUT -H "X-Container-Read: .r:*,.rlistings" -H "X-Auth-Token: ae93a81d50d643d8ae4d8cef67f667fb   

curl -s http://10.153.88.41:8080/v1/AUTH_e24d47652113493686492d2e7c04e601/hotchatting-X PUT -H "X-Container-Write: .r:*" -H "X-Auth-Token: 1ed0e9900cd84ecc9f6b71f3d7b2726c

 


Next, if you use keystone you need(!!!!) to set in /etc/swift/proxy-server.conf

[filter:authtoken]
paste.filter_factory = keystone.middleware.auth_token:filter_factory
# Delaying the auth decision is required to support token-less
# usage for anonymous referrers (‘.r:*’).
delay_auth_decision = 1

 然后可以匿名访问这个容器和下面的对象了

wget http://10.23.70.127:8080/v1/AUTH_f02c22db84c54525927353bab5d36b38/containertest2/setuptools-1.0.tar.gz


设置container读和写的权限

接口名称:

设置container读和写的权限(单独设置某一个账号对这个container的读或者写(读)的权限

接口定义:

curl -k -i -s http://localhost:8080/v1/AUTH_{Tenant_id}/{Container_id}/\
     -X PUT \
     -H "X-Container-Read: tenant_name:account_name"\

           -H "X-Container-Write:tenant_name:account_name"\

     -H "X-Auth-Token: { Token_id}"

传入参数定义:

Tenant_id:租户id
Container_name: 所删除的容器名称
Token_id:租户对应的token的id

返回结果:

返回201,表示成功

协议:

http

示例:

 curl -k -i -s http://10.23.70.127:8080/v1/AUTH_b9d8185513404fc7a85db0a257e2142a/testcontainer -H 'X-Container-Read: containertest:share1' -X PUT -D - -H "X-Auth-Token: 5d95cfbfe970498188fb0c568ed0670a" #containertest:share1这个账户对testcontainer有读的权限

 

2016-03-11 11:23:41 androidwd 阅读数 3812

1.    代码引入

<dependency>

              <groupId>org.pacesys</groupId>

              <artifactId>openstack4j</artifactId>

              <version>2.0.9</version>

              <classifier>withdeps</classifier>

</dependency>

2.    授权

Eg:

 

              OSClient os =OSFactory.builder()

                            .endpoint("http://192.168.137.140:5000/v2.0")

                            .credentials("username","userpassword").tenantName("tenantName")

                            .authenticate();

3.    Account账户

一个账户也被称为一个project工程或者一个tenant租户。一个账户给出了容器和对象存在的安全范围。由于账户角色的愿意,与它相关的管理任务并不多。

3.1          获取账户详情

eg:

SwiftAccount account =os.objectStorage().account().get();

3.2          元数据metadata

3.2.1     创建或者更新一个账户的元数据:

boolean successful =os.objectStorage().account().updateMetadata(myMetadataMap);

3.2.2     删除一个账户的元数据:

boolean successful =os.objectStorage().account().deleteMetadata(myMetadataMap);

 

4.    Containers容器

一个容器本章上就是一个存放对象的桶。

Containers can have access security assigned tothem, published against a CDN or be shared publicly.

4.1          容器的查询

列出当前账户的所有容器

List<? extendsSwiftContainer> containers = os.objectStorage().containers().list();

使用更进一步的条件查询

List<? extendsSwiftContainer> containers = os.objectStorage()

                                             .containers()

                                             .list(ContainerListOptions.create()

                                                      .startsWith("J")

                                                     .limit(100)

                                                     // ...

                                              );

4.2          创建容器

// Simple

os.objectStorage().containers().create("myContainerName");

      

// Full control

os.objectStorage().containers().create("myContainer",CreateUpdateContainerOptions.create()

                                                        .accessAnybodyRead()

                                                        .accessWrite(acl)

                                                        .metadata(myMeta)

                                                         //...

                                                      ); #### Updating a Container

更新容器信息与fullcontrol创建容器十分类似。唯一的不同就在于调用方法名称。简短示例:

os.objectStorage().containers().update("myContainer",CreateUpdateContainerOptions);

 

4.3          删除容器

注意:为了成功删除容器,必须在删除之前将他清空。这不是本代码的策略,而是openstack的限制就是如此。

os.objectStorage().containers().delete("myContainer");

 

4.4          创建伪目录

此功能可能由于你部署方式的配置不同而导致不支持。像Rackspace这样的供应商是开箱即支持的。

os.objectStorage().containers().createPath(containerName,"/my/nested/path");

 

4.5          元数据

读取

Map<String,String> md = os.objectStorage().containers().getMetadata(containerName);

创建及更新

boolean successful =os.objectStorage().containers().updateMetadata(containerName, myMetadataMap);

删除元数据

boolean successful =os.objectStorage().containers().deleteMetadata(containerName, myMetadataMap);

 

 

5.    Objects对象

对象就是被上传的文件,证明或者伪目录。对象是与容器相关联的。

5.1          查询

列出一个容器的所有对象

List<? extendsSwiftObject> objs = os.objectStorage().objects().list(containerName);

使用更进一步的条件查询

List<? extendsSwiftObject> objs =os.objectStorage().objects().list(ObjectListOptions.create()

                                       .startsWith("J")

                                       .path("/art/digital")

                                        // ...

                                     );

5.2          创建对象

简单的

String etag =os.objectStorage().objects().put(containerName, objectName,Payloads.create(someFile));

高级的

String etag =os.objectStorage().objects().put(containerName, objectName,

                                              Payloads.create(someFile),

                                              ObjectPutOptions.create()

                                                  .path("/some/path")

                                                 .metadata(md)

                                                 // ...

                                              );

5.3          删除对象

os.objectStorage().objects().delete(containerName,objectName);

5.4          复制对象

String etag =os.objectStorage().objects().copy(ObjectLocation.create(srcContainer,srcObject)

                                               ObjectLocation.create(destContainer, destObject)

                                               );

5.5          元数据

 

获取

Map<String,String> md = os.objectStorage().objects().getMetadata(containerName,objectName);

创建和更新

boolean successful =os.objectStorage().objects().updateMetadata(ObjectLocation.create(containerName,objectName), myMetadataMap);