Skip to content

Latest commit

 

History

History
559 lines (381 loc) · 17.7 KB

README.md

File metadata and controls

559 lines (381 loc) · 17.7 KB

UPYUN Python SDK

pypi package Build Status

UPYUN Python SDK,集合 UPYUN HTTP REST 接口UPYUN HTTP FORM 接口视频处理接口

更新说明

  1. 不再兼容 1.x 的版本,新版接口设计和实现更加 Pythonic,且代码风格完全符合 pep8 规范。
  2. 2.2.0 及以上版本同时兼容了最新版本的 Python 2.6 / 2.7 / 3.3 / 3.4。
  3. 2.3.0 及以上版本不再支持直接使用默认标准库 httplib,必须依赖 requests 这个第三方 HTTP Client 库。
  4. 2.5.0 及以上版本更新了 REST API,FORM API 以及预处理接口的签名算法,同时移除分块上传接口。

安装说明

安装第三方依赖库 requests: HTTP for Humans!

pip install requests

安装 UPYUN SDK

pip install upyun

运行测试用例

export UPYUN_SERVICE=<service>
export UPYUN_USERNAME=<username>
export UPYUN_PASSWORD=<password>

make init test

基本函数接口

初始化 UpYun

import upyun

up = upyun.UpYun('service', 'username', 'password', timeout=30, endpoint=upyun.ED_AUTO)

serviceusernamepassword 分别为服务名,授权操作员帐号,密码。timeout 为 HTTP 请求超时时间,默认 60 秒,可选。

由于直接在 SDK 中暴露密码可能存在安全隐患,因此对于安全性要求较高的用户,可使用如下远程签名方式:

import upyun

up = upyun.UpYun('service', username='username', auth_server='http://localhost:8080')

签名服务示例代码见 examples/auth_server.py

远程签名方式暂不支持缓存刷新功能

初始化示例
import upyun

up = upyun.UpYun('service', username='username', password='password')

以及,根据国内的网络情况,UPYUN API 目前提供了电信、联通网通、移动铁通三个接入点,在初始化时可由参数 endpoint 进行设置,其可选的值有:

upyun.ED_AUTO     # 根据网络条件自动选择接入点,默认
upyun.ED_TELECOM  # 电信接入点
upyun.ED_CNC      # 联通网通接入点
upyun.ED_CTT      # 移动铁通接入点

默认设置为 upyun.ED_AUTO ,但是我们推荐根据服务器网络状况,手动设置合理的接入点以获取最佳的访问速度。同时,也可通过:

up.<api>.endpoint = upyun.ED_TELECOM

在对象使用过程中更改,其中 <api> 为你所要调用接口,REST 为 up_rest,表单为 up_form,视频处理为 av

上传文件

直接传递文件内容的形式上传

up.put('/upyun-python-sdk/ascii.txt', 'abcdefghijklmnopqrstuvwxyz\n')

其中,方法 up.put 默认自动创建相应目录。

数据流方式上传,可降低内存占用

headers = { 'x-gmkerl-rotate': '180' }

with open('unix.png', 'rb') as f:
    res = up.put('/upyun-python-sdk/xinu.png', f, checksum=True, headers=headers)

其中,参数 checksumheaders 可选,前者默认 False,表示不进行 MD5 校验; 后者可根据需求设置自定义 HTTP Header,例如作图参数 x-gmkerl-* ,具体请参考 REST API 上传文件

上传成功,如果是图片类型文件,那么 res 返回的是一个包含图片长、宽、帧数和类型信息的 Python Dict 对象 ( 其他文件类型, 返回一个空的 Dict):

{'frames': '1', 'width': '1280', 'file-type': 'PNG', 'height': '800'}

上传失败,则抛出相应异常。

移动文件

up.move('/upyun-python-sdk/move-from.txt', '/upyun-python-sdk/move-to.txt')

第一个参数是源文件地址, 第二个参数是目的文件地址

拷贝文件

up.copy('/upyun-python-sdk/copy-from.txt', '/upyun-python-sdk/copy-to.txt')

第一个参数是源文件地址, 第二个参数是目的文件地址

断点续传

with open('unix.png', 'rb') as f:
    res = up.put('/upyun-python-sdk/xinu.png', f, checksum=True, need_resume=True)

参数 need_resume 默认 False, 置为 True 后, 采用断点续传方式上传文件。

from upyun import FileStore
from upyun import print_reporter

with open('unix.png', 'rb') as f:
    res = up.put('/upyun-python-sdk/xinu.png', f, checksum=True, need_resume=True, headers={'X-Upyun-Multi-Type': 'image/png'}, store=FileStore(), reporter=print_reporter)

参数 store 用来保存断点信息, 默认保存断点信息在内存中。 FileStore() 可以保存断点信息到文件, 注意文件夹的权限, 默认保存在 ~/.up-python-resume/, 提供参数 directory 用于修改默认的文件夹路径。 也可以选择继承 BaseStore 实现自己的断点存储。

参数 reporter 用于报告上传进度, 默认忽略上传进度。 print_reporter 只是 print 上传进度, 有需要的请继承 BaseReporter 自行处理。

可以使用头部 X-Upyun-Multi-Type 来指定待上传文件的 MIME 类型,默认 application/octet-stream,建议自行设置。

并发上传

并发上传是把文件按照part_size切割后,并发上传,都上传完毕后调用complete结束上传。
part_size取值1M(1024*1024)的整数倍,默认是1M。
下面的示例是并发上传一个2.5M的文件,数据内容是随机生成的。其中的upload方法可以多线程并发调用

uploader = up.init_multi_uploader(key) #初始化上传

#并发上传需要数据块
uploader.upload(2, os.urandom(512 * 1024))    
uploader.upload(0, os.urandom(1024 * 1024))
uploader.upload(1, os.urandom(1024 * 1024))
res = uploader.complete() #所有块都上传完毕后,调用结束

一次上传没有完成, 可以把uploader.upload_id的值保存下来, 下次继续上传

uploader = up.init_multi_uploader(remote_file, upload_id=uploader.upload_id)

如果有需要,可以列出来已经上传成功的parts

datas = uploader.list_uploaded_parts() 

返回一个json结构的数组

[{
    "id": 0,
    "suze": 1048576,
    "etag": "cf97350abc2b45804d09a829b55eeeaf",
}]

若在上传过程中不需要上传了,可以调用uploader.cancel()取消上传任务。取消的任务无法再继续上传。

表单方式上传

用户可直接上传文件到 UPYUN,而不需要通过客户服务器进行中转。

kwargs = { 'allow-file-type': 'jpg,jpeg,png',
           'notify-url': 'http://httpbin.org/post', }

with open('unix.png', 'rb') as f:
    res = up.put('/upyun-python-sdk/xinu.png', f, checksum=True, form=True, **kwargs)

其中,参数 form 表示是否使用表单上传方式,必选。

同时表单上传可携带许多额外的可选参数,可以组合成字典作为函数可选参数传入,例如表单参数 allow-file-type ,具体请参考 表单 API 参数

表单上传还支持同步通知及异步通知机制,可以通过设置 return-urlnotify-url 来指定 URL。具体请参考通知规则

上传成功,如果是图片类型文件,那么 res 返回的是一个包含图片长、宽、帧数、类型信息、图片上传地址、返回状态码、返回状态信息和 signature 的 Python Dict 对象 (其他文件类型,则返回信息不包括图片长、宽和帧数参数):

{u'code': 200, u'image-height': 410, u'url': u'/upyun-python-sdk/xinu.png', u'image-frames': 1, u'sign': u'60e63662202e50bddedd01f8ca601ba5', u'image-type': u'PNG', u'time': 1450783577, u'message': u'ok', u'image-width': 1000}

下载文件

直接读取文件内容

res = up.get('/upyun-python-sdk/ascii.txt')

下载成功,返回文件内容; 失败则抛出相应异常。

使用数据流模式下载,节省内存占用

with open('xinu.png', 'wb') as f:
    up.get('/upyun-python-sdk/xinu.png', f)

下载成功,返回 Python None 对象; 失败则抛出相应异常。

创建目录

up.mkdir('/upyun-python-sdk/temp/')

创建成功,返回 Python None 对象; 失败则抛出相应异常。

删除目录或文件

up.delete('/upyun-python-sdk/xinu.png')
up.delete('/upyun-python-sdk/temp/')

删除成功,返回 Python None 对象; 失败则抛出相应异常。注意删除目录时,必须保证目录为空。

获取目录文件列表

res = up.getlist('/upyun-python-sdk/')

获取成功,返回一个包含该目录下所有目录或文件条目信息的 Python List 对象:

[{'time': '1363247311', 'type': 'F', 'name': 'temp', 'size': '0'}, {'time': '1363247311', 'type': 'N', 'name': 'xinu.png', 'size': '477908'}]

其中每个条目信息是又是一个 Python Dict 对象:

item = res[0]
print item['name'] # 文件名称
print item['type'] # 文件类型
print item['size'] # 文件大小
print item['time'] # 创建时间

获取失败,则抛出相应的异常。该方法默认获取根目录列表信息。

分页功能

res = up.getlist('/upyun-python-sdk/', limit=10, order='asc', begin='xxx')

三个分页参数,默认为空,具体含义请参见 分页参数

分页获取文件

res = get_list_with_iter('/upyun-python-sdk/', limit=10, order='asc', begin='xxx')

{
	'files': [{
		'name': 'xxx.m4a',
		'type': 'N',
		'size': '332918',
		'time': '1449137388'
	}],
	'iter': 'xxxxx'
}

三个分页参数,默认为空,具体含义请参见 分页参数

流式返回

iter_items = up.iterlist('/upyun-python-sdk/', limit=10, order='asc', begin='xxx')
# the resulting iterator object
for item in iter_items:
    print(item['type'], item['name'], item['size'])

三个分页参数,默认为空,具体含义请参见 分页参数

获取文件信息

res = up.getinfo('/upyun-python-sdk/xinu.png')
print res['file-type']
print res['file-size']
print res['file-date']

获取成功,返回一个 Python Dict 对象; 失败则抛出相应异常。

获取服务使用情况

res = up.usage()

获取成功,始终返回该服务当前使用的总容量,单位 Bytes,值类型为 Python String 对象; 失败则抛出相应异常。

视频处理

用于处理已经上传到对应存储服务中的视频文件,进行转码、截图等操作。

source = '/service/test.mp4'
tasks = [{'type': 'probe', }, {'type': 'hls', 'hls_time': '100'}]
notify_url = 'http://httpbin.org/post'
up.pretreat(tasks, source, notify_url)

tasks 为提交的任务数据,需将所有任务组成数组,若仅有一个任务,也应组成数组结构,必选。UPYUN 的视频处理服务目前支持四种类型的处理请求:

  • 视频转码
  • HLS 切割
  • 视频截图
  • 视频信息获取

具体请参考视频处理参数

notify_url 为异步回调地址,在处理完成之后将会以 HTTP POST 请求进行异步通知,参考回调参数, 必选。source 为待处理源文件路径,需提供已上传文件的相对路径。

视频处理任务提交成功,则会针对提交的处理任务返回一组唯一的 task_id,可以根据这个 task_id 查询处理进度,如:

[
    '35f0148d414a688a275bf915ba7cebb2',
    '98adbaa52b2f63d6d7f327a0ff223348',
    ...
]

任务提交失败则会抛出相应异常。

视频处理进度查询

ids = ['35f0148d414a688a275bf915ba7cebb2','98adbaa52b2f63d6d7f327a0ff223348', ...]
up.status(ids)

以视频处理接口返回的数组作为传入参数,需为 Python List 结构。

返回的数据示例如下:

{
    tasks: {
        35f0148d414a688a275bf915ba7cebb2: 100,
        98adbaa52b2f63d6d7f327a0ff223348: null,
        ...
    }
}

特别的,当值为 null 时,表示没有查询到相关的任务信息。同时,由于视频处理所用时间较长,当提交任务后立刻去查询进度,也有可能会返回 null。

异步任务提交

notify_url = 'http://httpbin.org/post'                          // 回调地址

compress_tasks = [
    {
        "sources": ["a/b/c/source/1.jpg","a/b/c/source/2.jpg"],
        "save_as": "/result/t.zip",
        "home_dir": "a/b/c"
    },
]

print up.put_tasks(compress_tasks, notify_url, 'compress')

depress_tasks = [
    {
        "sources": "/source/t.zip",              //UPYUN 存储服务中内文件路径
        "save_as": "/result/t/",                 //保存路径
    },
]

print up.put_tasks(depress_tasks, notify_url, 'depress')

fetch_tasks = [
    {
        'url': 'http://www.upyun.com/index.html',               // 需要拉取文件的 URL
        'random': False,                                        // 是否追加随机数, 默认 false
        'overwrite': True,                                      // 是否覆盖,默认 true
        'save_as': '/site/index.html',                          // 保存路径
    }
]

print up.put_tasks(fetch_tasks, notify_url, 'spiderman')

具体请参考 压缩解压缩异步文件拉取

异常处理

try:
    res = up.usage()

    # do something else

except upyun.UpYunServiceException as se:
    print 'Except an UpYunServiceException ...'
    print 'Request Id: ' + se.request_id
    print 'HTTP Status Code: ' + str(se.status)
    print 'Error Message:    ' + se.msg + '\n'
except upyun.UpYunClientException as ce:
    print 'Except an UpYunClientException ...'
    print 'Error Message: ' + ce.msg + '\n'

其中, UpYunServiceException 主要是 UPYUN 端返回的错误信息,具体错误代码请参考 标准 API 错误代码表; 而 UpYunClientException 则主要是一些客户端环境的异常,例如客户端网络超时,或客户端参数不完整等。

高级特性

自定义数据流大小

up = upyun.UpYun('service', 'username', 'password', chunksize=8192)

当通过数据流方式上传和下载文件时,chunksize 决定了每次读操作的缓存区大小,默认 8192 字节。

自定义文件上传和下载过程

例如,通过如下代码可以很容易实现上传下载的进度条显示:

from progressbar import *

class ProgressBarHandler(object):
    def __init__(self, totalsize, params):
        widgets = [params, Percentage(), ' ',
                   Bar(marker='=', left='[', right=']'), ' ',
                   ETA(), ' ', FileTransferSpeed()]
        self.pbar = ProgressBar(widgets=widgets, maxval=totalsize).start()

    def update(self, readsofar):
        self.pbar.update(readsofar)

    def finish(self):
        self.pbar.finish()

with open('unix.png', 'rb') as f:
    res = up.put('xinu.png', f, handler=ProgressBarHandler, params='Uploading ')

with open('xinu.png', 'wb') as f:
    up.get('xinu.png', f, handler=ProgressBarHandler, params='Downloading ')

原图密钥保护

with open('unix.png', 'rb') as f:
    res = up.put('xinu.png', f, secret="abc")

其中参数 secret 可指定具体密钥内容;默认 None,表示不设置密钥。特别地,该功能仅对配置了缩略图版本号的图片服务有效。

详见 UPYUN HTTP REST API 接口 中关于原图密钥保护的说明。

缓存刷新

基于 UPYUN 缓存刷新 API 接口 开发,方便对 CDN 服务缓存资源进行主动刷新。

特别地,云存储服务正常情况下,资源更新则不需要额外提交刷新请求,缓存系统会自动进行处理。

>>> print up.purge('/upyun-python-sdk/xinu.png')
[]
>>> print up.purge(['/unix.png', '/xinu.png'], domain='invalid.upyun.com')
['/unix.png', '/unix.png']

支持提交单个或一组 URI 到缓存刷新队列,其中 domain 参数可特别指定为该服务对应的绑定域名作为本次刷新的域,默认其值为 None,表示始终使用默认域名。

提交成功,返回一个 Python List 对象,包含本次提交中无效的 URI 列表;失败则抛出相应异常。

签名验证

如果在表单或异步任务提交接口使用了 return-urlnotify-url 等通知方法后,回调结果信息头会包含 Authorization 字段,用于验证回调信息是否正确。

import upyun

up = upyun.UpYun('service', 'username', 'password')

headers = {
    'Date': 'Fri, 20 Jan 2017 08:46:20 GMT',
    'Content-MD5': 'd36489794822f8d33fd28217d8a5bed4',
    'Authorization': 'UPYUN username:W738BergX15B+jso8fSPzKd0/zQ='
}

assert up.verify_signature(headers['Authorization'], '/api/v1/echo', headers)

远程签名服务

创建自己的远程签名服务以提供签名功能。实现 API 如下:

URL:任意合法 URL

HTTP 方法:POST

文档格式:JSON

请求参数:

参数名称 必选 类型
username true string
method true string
uri true string
date true stirng
policy false string
content_md5 false string

返回结果: UPYUN: username:signature

参数说明及签名算法见签名算法