kodocli

package
v1.0.6 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 25, 2021 License: MIT Imports: 36 Imported by: 0

Documentation

Overview

包 qiniupkg.com/api.v7/kodocli 提供了在客户端调用七牛云存储部分服务的能力

客户端,严谨说是非可信环境,主要是指在用户端执行的环境,比如:Android/iOS 设备、Windows/Mac/Linux 桌面环境、也包括浏览器(如果浏览器能够执行 Go 语言代码的话)。

注意,在这种场合下您不应该在任何地方配置 AccessKey/SecretKey。泄露 AccessKey/SecretKey 如同泄露您的用户名/密码一样十分危险,会影响您的数据安全。

第一个问题是如何上传文件。因为是在非可信环境,所以我们首先是要授予它有上传文件的能力。答案是给它颁发上传凭证。假设服务端也是 Go 语言,那么:

import "qiniupkg.com/api.v7/kodo"

kodo.SetMac("your-access-key", "your-secret-key") // 配置 AccessKey/SecretKey

zone := 0
c := kodo.New(zone, nil) // 创建一个 Client 对象

bucket := "your-bucket-name"
key := "foo/bar.jpg"
policy := &kodo.PutPolicy{
	Scope: bucket + ":" + key, // 上传文件的限制条件,这里限制只能上传一个名为 "foo/bar.jpg" 的文件
	Expires: 3600, // 这是限制上传凭证(uptoken)的过期时长,3600 是一小时
	...
}
uptoken := c.MakeUptoken(policy) // 生成上传凭证

生成上传凭证之后,通过某种方式将 uptoken 发送到客户端。这样客户端就可以上传文件了:

zone := 0
uploader := kodocli.NewUploader(zone, nil)
ctx := context.Background()

key := "foo/bar.jpg"
localFile := "/your/local/image/file.jpg"
err := uploader.PutFile(ctx, nil, uptoken, key, localFile, nil)
if err != nil {
	... // 上传文件失败处理
	return
}

注意,如果客户端上传的 key 不是 uptoken 所要求的 "foo/bar.jpg",那么上传就会被拒绝。

如果我们希望一个 uptoken 可以上传多个文件,那么服务端颁发 uptoken 的代码需要调整下:

bucket := "your-bucket-name"
policy := &kodo.PutPolicy{
	Scope: bucket, // 上传文件的限制条件,这里是只限制了要上传到 "your-bucket-name" 空间
	Expires: 3600, // 这是限制上传凭证(uptoken)的过期时长,3600 是一小时
	...
}
uptoken := c.MakeUptoken(policy)

颁发这样的 uptoken 给客户端,客户端就可以用它上传任意名字(key)的文件,前提是服务器上还没有同名的文件。

特别需要注意的是,这种情况下服务端会拒绝已经有同名文件的上传请求,而不是覆盖服务器上已有的文件。这是出于数据安全的考虑。我们并不非常推荐 uptoken 复用的做法,除了注意文件名可能冲突外,还需要注意 uptoken 是有时效的,过期就需要重新向服务器申请新的上传凭证。

搞定文件的上传后,第二个问题是如何下载文件。如果是公开文件,我们只需要:

import "net/http"

domain := "domain-of-your-bucket.com" // 您的空间绑定的域名,这个可以在七牛的Portal中查到
baseUrl := kodocli.MakeBaseUrl(domain, "foo/bar.jpg") // 得到下载 url
resp, err := http.Get(baseUrl)
...

但是对于私有空间,事情要复杂一些,需要客户端向您的业务服务器申请下载该文件。业务服务器确认该用户有权访问,则返回一个临时有效的 privateUrl。具体如何生成 privateUrl,可以看服务端 SDK 相关的文档介绍。

Index

Constants

View Source
const (
	LOG_LEVEL_DEBUG = iota
	LOG_LEVEL_INFO
	LOG_LEVEL_WARN
	LOG_LEVEL_ERROR
	LOG_LEVEL_FATAL
)
View Source
const (
	TypeNormal = iota
	TypeLine
)
View Source
const (
	DontCheckCrc    uint32 = 0
	CalcAndCheckCrc        = 1
)
View Source
const (
	InvalidCtx = 701 // UP: 无效的上下文(bput),可能情况:Ctx非法或者已经被淘汰(太久未使用)
)

Variables

View Source
var (
	ErrInvalidPutProgress = errors.New("invalid put progress")
	ErrPutFailed          = errors.New("resumable put failed")
	ErrUnmatchedChecksum  = errors.New("unmatched checksum")
)
View Source
var (
	MaxContinuousFailureTimes    = 5
	MaxContinuousFailureDuration = 1 * time.Minute
	MaxFindHostsPrecent          = 50
)
View Source
var ErrMd5NotMatch = httputil.NewError(406, "md5 not match")

Functions

func BlockCount

func BlockCount(fsize int64) int

func MakeAuthTokenString

func MakeAuthTokenString(key, secret string, auth *AuthPolicy) string

func MakeBaseUrl

func MakeBaseUrl(domain, key string) (baseUrl string)

根据空间(Bucket)的域名,以及文件的 key,获得 baseUrl。 如果空间是 public 的,那么通过 baseUrl 可以直接下载文件内容。 如果空间是 private 的,那么需要对 baseUrl 进行私有签名得到一个临时有效的 privateUrl 进行下载。

func NewLogger

func NewLogger() *logger

func NewSectionReader

func NewSectionReader(r io.Reader, n int64) *sectionReader

func SetAppName

func SetAppName(userApp string) error

设置使用这个SDK的应用程序名。userApp 必须满足 [A-Za-z0-9_\ \-\.]*

func SetLogger

func SetLogger(logger Ilog)

func SetSettings

func SetSettings(v *Settings)

Types

type AuthPolicy

type AuthPolicy struct {
	Scope               string   `json:"scope"`
	IsPrefixalScope     uint16   `json:"isPrefixalScope,omitempty"` // 若为非0,则Scope的key部分表示为前缀限定
	CallbackUrl         string   `json:"callbackUrl,omitempty"`
	CallbackHost        string   `json:"callbackHost,omitempty"`
	CallbackBodyType    string   `json:"callbackBodyType,omitempty"`
	CallbackBody        string   `json:"callbackBody,omitempty"`
	CallbackFetchKey    uint16   `json:"callbackFetchKey,omitempty"` // 先回调取得key再改名 https://pm.qbox.me/issues/11851
	CallbackTimeout     uint16   `json:"callbackTimeout,omitempty"`  // 允许自定义超时需求 https://pm.qbox.me/issues/21576
	Customer            string   `json:"customer,omitempty"`
	EndUser             string   `json:"endUser,omitempty"`
	Transform           string   `json:"transform,omitempty"`
	FopTimeout          uint32   `json:"fopTimeout,omitempty"`
	Deadline            int64    `json:"deadline"`         // 截止时间(以秒为单位)原来是uint32 上限为到2106年 如果用户设置过期时间超过了这个上限就会鉴权失败 请各单位如果编译不过自行调整https://pm.qbox.me/issues/25718
	Escape              uint16   `json:"escape,omitempty"` // 是否允许存在转义符号
	DetectMime          uint16   `json:"detectMime,omitempty"`
	Exclusive           uint16   `json:"exclusive,omitempty"`       // 若为非0, 即使Scope为"Bucket:key"的形式也是insert only
	InsertOnly          uint16   `json:"insertOnly,omitempty"`      // Exclusive 的别名
	ForceInsertOnly     bool     `json:"forceInsertOnly,omitempty"` // 若为true,即使上传hash相同的文件也会报文件已存在,优先级高于InsertOnly
	ReturnBody          string   `json:"returnBody,omitempty"`
	SignReturnBody      uint16   `json:"signReturnBody,omitempty"` // 默认不开启签名,需要用户的 AK SK
	ReturnURL           string   `json:"returnUrl,omitempty"`
	FsizeMin            int64    `json:"fsizeMin,omitempty"`
	FsizeLimit          int64    `json:"fsizeLimit,omitempty"`
	MimeLimit           string   `json:"mimeLimit,omitempty"`
	SaveKey             string   `json:"saveKey,omitempty"`
	ForceSaveKey        bool     `json:"forceSaveKey,omitempty"`
	PersistentOps       string   `json:"persistentOps,omitempty"`
	PersistentNotifyUrl string   `json:"persistentNotifyUrl,omitempty"`
	PersistentPipeline  string   `json:"persistentPipeline,omitempty"`
	Checksum            string   `json:"checksum,omitempty"`
	Accesses            []string `json:"accesses,omitempty"`
	DeleteAfterDays     uint32   `json:"deleteAfterDays,omitempty"`
	FileType            FileType `json:"fileType,omitempty"`
	NotifyQueue         string   `json:"notifyQueue,omitempty"`
	NotifyMessage       string   `json:"notifyMessage,omitempty"`
	NotifyMessageType   string   `json:"notifyMessageType,omitempty"`
	CustomEventMessage  string   `json:"customEventMessage,omitempty"`
	//内部参数
	OldFh   string `json:"oldFh,omitempty"`
	PutTime int64  `json:"putTime,omitempty"`
	Cond    string `json:"cond,omitempty"` //格式:condKey1=condVal1&condKey2=condVal2,支持hash、mime、fsize、putTime条件,只有条件匹配才会执行覆盖操作
}

type BlkputRet

type BlkputRet struct {
	Ctx      string `json:"ctx"`
	Checksum string `json:"checksum"`
	Crc32    uint32 `json:"crc32"`
	Offset   uint32 `json:"offset"`
	Host     string `json:"host"`
}

type CompleteMultipart

type CompleteMultipart struct {
	Parts      []Part            `json:"parts"`
	Fname      string            `json:"fname"`
	MimeType   string            `json:"mimeType"`
	Metadata   map[string]string `json:"metadata"`
	CustomVars map[string]string `json:"customVars"`
}

func (*CompleteMultipart) Len

func (p *CompleteMultipart) Len() int

func (*CompleteMultipart) Less

func (p *CompleteMultipart) Less(i, j int) bool

func (*CompleteMultipart) Sort

func (p *CompleteMultipart) Sort()

func (*CompleteMultipart) Swap

func (p *CompleteMultipart) Swap(i, j int)

type CompletePartsRet

type CompletePartsRet struct {
	Hash string `json:"hash"`
	Key  string `json:"key"`
}

type FileType

type FileType uint32

type Ilog

type Ilog interface {
	Debug(v ...interface{})
	Info(v ...interface{})
	Warn(v ...interface{})
	Error(v ...interface{})
	Fatal(v ...interface{})
}

type Part

type Part struct {
	PartNumber int    `json:"partNumber"`
	Etag       string `json:"etag"`
}

type PutExtra

type PutExtra struct {
	// 可选,用户自定义参数,必须以 "x:" 开头。若不以x:开头,则忽略。
	Params map[string]string
	XMeta  map[string]string

	// 可选,当为 "" 时候,服务端自动判断。
	MimeType string

	//CRC32校验
	Crc32 uint32
	//Content-Md5 Trailer
	Md5Trailer func() []byte
	// 上传事件:进度通知。这个事件的回调函数应该尽可能快地结束。
	OnProgress func(fsize, uploaded int64)
}

上传的额外可选项

type PutRet

type PutRet struct {
	Hash         string `json:"hash"`
	PersistentId string `json:"persistentId"`
	Key          string `json:"key"`
}

如果 uptoken 没有指定 ReturnBody,那么返回值是标准的 PutRet 结构

type RputExtra

type RputExtra struct {
	Params     map[string]string                             // 可选。用户自定义参数,以"x:"开头 否则忽略
	XMeta      map[string]string                             // 可选。
	MimeType   string                                        // 可选。
	ChunkSize  int                                           // 可选。每次上传的Chunk大小
	TryTimes   int                                           // 可选。尝试次数
	Progresses []BlkputRet                                   // 可选。上传进度
	Notify     func(blkIdx int, blkSize int, ret *BlkputRet) // 可选。进度提示(注意多个block是并行传输的)
	NotifyErr  func(blkIdx int, blkSize int, err error)
}

type Settings

type Settings struct {
	TaskQsize int // 可选。任务队列大小。为 0 表示取 Workers * 4。
	Workers   int // 并行 Goroutine 数目。
	ChunkSize int // 默认的Chunk大小,不设定则为256k
	TryTimes  int // 默认的尝试次数,不设定则为3
}

type UploadConfig

type UploadConfig struct {
	UpHosts        []string
	Transport      http.RoundTripper
	UploadPartSize int64
	Concurrency    int
	UseBuffer      bool
}

type UploadPartRet

type UploadPartRet struct {
	Etag string `json:"etag"`
	Md5  string `json:"md5"`
}

type Uploader

type Uploader struct {
	Conn           rpc.Client
	UpHosts        []string
	UploadPartSize int64
	Concurrency    int
	UseBuffer      bool
}

func NewUploader

func NewUploader(zone int, cfg *UploadConfig) (p Uploader)

func (Uploader) Put2

func (p Uploader) Put2(
	ctx Context, ret interface{}, uptoken, key string, data io.ReaderAt, size int64, extra *PutExtra) error

上传一个文件,普通上传。

ctx 是请求的上下文。 ret 是上传成功后返回的数据。如果 uptoken 中没有设置 CallbackUrl 或 ReturnBody,那么返回的数据结构是 PutRet 结构。 uptoken 是由业务服务器颁发的上传凭证。 key 是要上传的文件访问路径。比如:"foo/bar.jpg"。注意我们建议 key 不要以 '/' 开头。另外,key 为空字符串是合法的。 data 是文件内容的访问接口(io.Reader)。 fsize 是要上传的文件大小。 extra 是上传的一些可选项。详细见 PutExtra 结构的描述。

func (Uploader) PutFile

func (p Uploader) PutFile(
	ctx Context, ret interface{}, uptoken, key, localFile string, extra *PutExtra) (err error)

上传一个文件。 和 Put 不同的只是一个通过提供文件路径来访问文件内容,一个通过 io.Reader 来访问。

ctx 是请求的上下文。 ret 是上传成功后返回的数据。如果 uptoken 中没有设置 CallbackUrl 或 ReturnBody,那么返回的数据结构是 PutRet 结构。 uptoken 是由业务服务器颁发的上传凭证。 key 是要上传的文件访问路径。比如:"foo/bar.jpg"。注意我们建议 key 不要以 '/' 开头。另外,key 为空字符串是合法的。 localFile 是要上传的文件的本地路径。 extra 是上传的一些可选项。详细见 PutExtra 结构的描述。

func (Uploader) PutFileWithoutKey

func (p Uploader) PutFileWithoutKey(
	ctx Context, ret interface{}, uptoken, localFile string, extra *PutExtra) (err error)

上传一个文件。文件的访问路径(key)自动生成。 如果 uptoken 中设置了 SaveKey,那么按 SaveKey 要求的规则生成 key,否则自动以文件的 hash 做 key。 和 RputWithoutKey 不同的只是一个通过提供文件路径来访问文件内容,一个通过 io.Reader 来访问。

ctx 是请求的上下文。 ret 是上传成功后返回的数据。如果 uptoken 中没有设置 CallbackUrl 或 ReturnBody,那么返回的数据结构是 PutRet 结构。 uptoken 是由业务服务器颁发的上传凭证。 localFile 是要上传的文件的本地路径。 extra 是上传的一些可选项。详细见 PutExtra 结构的描述。

func (Uploader) Rput

func (p Uploader) Rput(
	ctx Context, ret interface{}, uptoken string,
	key string, f io.ReaderAt, fsize int64, extra *RputExtra) error

上传一个文件,支持断点续传和分块上传。

ctx 是请求的上下文。 ret 是上传成功后返回的数据。如果 uptoken 中没有设置 CallbackUrl 或 ReturnBody,那么返回的数据结构是 PutRet 结构。 uptoken 是由业务服务器颁发的上传凭证。 key 是要上传的文件访问路径。比如:"foo/bar.jpg"。注意我们建议 key 不要以 '/' 开头。另外,key 为空字符串是合法的。 f 是文件内容的访问接口。考虑到需要支持分块上传和断点续传,要的是 io.ReaderAt 接口,而不是 io.Reader。 fsize 是要上传的文件大小。 extra 是上传的一些可选项。详细见 RputExtra 结构的描述。

func (Uploader) RputFile

func (p Uploader) RputFile(
	ctx Context, ret interface{}, uptoken, key, localFile string, extra *RputExtra) (err error)

上传一个文件,支持断点续传和分块上传。 和 Rput 不同的只是一个通过提供文件路径来访问文件内容,一个通过 io.ReaderAt 来访问。

ctx 是请求的上下文。 ret 是上传成功后返回的数据。如果 uptoken 中没有设置 CallbackUrl 或 ReturnBody,那么返回的数据结构是 PutRet 结构。 uptoken 是由业务服务器颁发的上传凭证。 key 是要上传的文件访问路径。比如:"foo/bar.jpg"。注意我们建议 key 不要以 '/' 开头。另外,key 为空字符串是合法的。 localFile 是要上传的文件的本地路径。 extra 是上传的一些可选项。详细见 RputExtra 结构的描述。

func (Uploader) RputFileWithoutKey

func (p Uploader) RputFileWithoutKey(
	ctx Context, ret interface{}, uptoken, localFile string, extra *RputExtra) (err error)

上传一个文件,支持断点续传和分块上传。文件的访问路径(key)自动生成。 如果 uptoken 中设置了 SaveKey,那么按 SaveKey 要求的规则生成 key,否则自动以文件的 hash 做 key。 和 RputWithoutKey 不同的只是一个通过提供文件路径来访问文件内容,一个通过 io.ReaderAt 来访问。

ctx 是请求的上下文。 ret 是上传成功后返回的数据。如果 uptoken 中没有设置 CallbackUrl 或 ReturnBody,那么返回的数据结构是 PutRet 结构。 uptoken 是由业务服务器颁发的上传凭证。 localFile 是要上传的文件的本地路径。 extra 是上传的一些可选项。详细见 RputExtra 结构的描述。

func (Uploader) RputWithoutKey

func (p Uploader) RputWithoutKey(
	ctx Context, ret interface{}, uptoken string, f io.ReaderAt, fsize int64, extra *RputExtra) error

上传一个文件,支持断点续传和分块上传。文件的访问路径(key)自动生成。 如果 uptoken 中设置了 SaveKey,那么按 SaveKey 要求的规则生成 key,否则自动以文件的 hash 做 key。

ctx 是请求的上下文。 ret 是上传成功后返回的数据。如果 uptoken 中没有设置 CallbackUrl 或 ReturnBody,那么返回的数据结构是 PutRet 结构。 uptoken 是由业务服务器颁发的上传凭证。 f 是文件内容的访问接口。考虑到需要支持分块上传和断点续传,要的是 io.ReaderAt 接口,而不是 io.Reader。 fsize 是要上传的文件大小。 extra 是上传的一些可选项。详细见 RputExtra 结构的描述。

func (Uploader) StreamUpload

func (p Uploader) StreamUpload(ctx context.Context, ret interface{}, uptoken, key string, reader io.Reader, partNotify func(partIdx int, etag string)) error

func (Uploader) StreamUploadWithoutKey

func (p Uploader) StreamUploadWithoutKey(ctx context.Context, ret interface{}, uptoken string, reader io.Reader, partNotify func(partIdx int, etag string)) error

func (Uploader) Upload

func (p Uploader) Upload(ctx context.Context, ret interface{}, uptoken string, key string, f io.ReaderAt, fsize int64,
	mp *CompleteMultipart, partNotify func(partIdx int, etag string)) error

func (Uploader) UploadWithParts

func (p Uploader) UploadWithParts(ctx context.Context, ret interface{}, uptoken string, key string, f io.ReaderAt, fsize int64, uploadParts []int64,
	mp *CompleteMultipart, partNotify func(partIdx int, etag string)) error

func (Uploader) UploadWithoutKey

func (p Uploader) UploadWithoutKey(ctx context.Context, ret interface{}, uptoken string, f io.ReaderAt, fsize int64,
	mp *CompleteMultipart, partNotify func(partIdx int, etag string)) error

func (Uploader) UploadWithoutKeyWithParts

func (p Uploader) UploadWithoutKeyWithParts(ctx context.Context, ret interface{}, uptoken string, f io.ReaderAt, fsize int64, uploadParts []int64,
	mp *CompleteMultipart, partNotify func(partIdx int, etag string)) error

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL