Go实战--golang上传文件到七牛云对象存储(github.com/qiniu/api.v7)

生命不止,继续 go go go !!!

在国内,七牛绝对是golang的领导者。

七牛云

关于七牛:
(七牛云)隶属于上海七牛信息技术有限公司,七牛云是国内领先的企业级云服务商,专注于以数据管理为中心的云计算业务研发和运营,围绕富媒体场景推出了对象存储、融合 CDN 加速、容器计算云、大数据平台、人工智能平台等产品,并提供一站式视频云解决方案。公司目前已位列国内云计算行业第一阵营,为 70 多万家企业提供服务。

官网:
https://www.qiniu.com

接下来开始七牛之旅:

注册

验证

支付宝验证

添加资源(对象存储):
输入存储空间名称,也就是bucket
选择存储区域,有华东、华北、华南、北美
选择访问控制,有公开空间和私有空间选择

Go SDK

关于对象存储,七牛云提供了Golang版本的SDK。

文档地址
https://developer.qiniu.com/kodo/sdk/1238/go

简介
此 SDK 适用于 Go 1.7.0 及以上版本。使用此 SDK 构建您的网络应用程序,能让您以非常便捷的方式将数据安全地存储到七牛云上。无论您的网络应用是一个网站程序,还是包括从云端(服务端程序)到终端(手持设备应用)的架构服务和应用,通过七牛云及其 SDK,都能让您应用程序的终端用户高速上传和下载,同时也让您的服务端更加轻盈。

Go SDK 属于七牛服务端SDK之一,主要有如下功能:

提供生成客户端上传所需的上传凭证的功能
提供文件从服务端直接上传七牛的功能
提供对七牛空间中文件进行管理的功能
提供对七牛空间中文件进行处理的功能
提供七牛CDN相关的刷新,预取,日志功能

获取

go get -u github.com/qiniu/api.v7

获取的时候出现错误:

# cd D:\go_workspace\src\golang.org\x\net; git pull --ff-only
fatal: unable to access 'https://go.googlesource.com/net/': Failed to connect to go.googlesource.com port 443: Timed out
package golang.org/x/net/context: exit status 1

原因呢,你懂的,自己想办法解决~~~

上传文件

七牛文件上传分为客户端上传(主要是指网页端和移动端等面向终端用户的场景)和服务端上传两种场景,具体可以参考文档七牛业务流程

这里跟大家分享的,主要是客户端上传。

服务端SDK在上传方面主要提供两种功能,一种是生成客户端上传所需要的上传凭证,另外一种是直接上传文件到云端。

相关知识介绍

Access Key 和 Secret Key
在七牛云的控制面板中, 个人中心,密钥管理中可以查看自己的*Access Key 和 Secret Key。

客户端上传凭证
客户端(移动端或者Web端)上传文件的时候,需要从客户自己的业务服务器获取上传凭证,而这些上传凭证是通过服务端的SDK来生成的,然后通过客户自己的业务API分发给客户端使用。根据上传的业务需求不同,七牛云 Go SDK支持丰富的上传凭证生成方式。

这里的bucket即你在七牛云设置的存储空间名称,accessKey,secretKey即上面提到的。

putPolicy := storage.PutPolicy{
        Scope: bucket,}
    mac := qbox.NewMac(accessKey,secretKey)
    upToken := putPolicy.UploadToken(mac)

表示文件上传的上传策略

type PutPolicy struct {
    Scope               string `json:"scope"`
    Expires             uint32 `json:"deadline"` // 截止时间(以秒为单位)
    IsPrefixalScope     int    `json:"isPrefixalScope,omitempty"`
    InsertOnly          uint16 `json:"insertOnly,omitempty"` // 若非0,即使Scope为 Bucket:Key 的形式也是insert only
    DetectMime          uint8  `json:"detectMime,则服务端根据内容自动确定 MimeType
    FsizeLimit          int64  `json:"fsizeLimit,omitempty"`
    MimeLimit           string `json:"mimeLimit,omitempty"`
    SaveKey             string `json:"saveKey,omitempty"`
    CallbackFetchKey    uint8  `json:"callbackFetchKey,omitempty"`
    CallbackURL         string `json:"callbackUrl,omitempty"`
    CallbackHost        string `json:"callbackHost,omitempty"`
    CallbackBody        string `json:"callbackBody,omitempty"`
    CallbackBodyType    string `json:"callbackBodyType,omitempty"`
    ReturnURL           string `json:"returnUrl,omitempty"`
    ReturnBody          string `json:"returnBody,omitempty"`
    PersistentOps       string `json:"persistentOps,omitempty"`
    PersistentNotifyURL string `json:"persistentNotifyUrl,omitempty"`
    PersistentPipeline  string `json:"persistentPipeline,omitempty"`
    EndUser             string `json:"endUser,omitempty"`
    DeleteAfterDays     int    `json:"deleteAfterDays,omitempty"`
    FileType            int    `json:"fileType,omitempty"`
}

指定凭证有效时间
默认情况下,在不指定上传凭证的有效时间情况下,默认有效期为1个小时。也可以自行指定上传凭证的有效期:

putPolicy.Expires = 3600 //1小时有效期

这里的时间单位是秒。

构建配置类
七牛存储支持空间创建在不同的机房,在使用七牛的 Go SDK 中的FormUploader和ResumeUploader上传文件之前,必须要构建一个上传用的Config对象,在该对象中,可以指定空间对应的zone以及其他的一些影响上传的参数。

Config 为文件上传,资源管理等配置

type Config struct {
    Zone          *Zone //空间所在的机房
    UseHTTPS      bool  //是否使用https域名
    UseCdnDomains bool  //是否使用cdn加速域名
}

我们可以这么写:

cfg := storage.Config{}
// 空间对应的机房
cfg.Zone = &storage.ZoneHuadong

// 是否使用https域名
cfg.UseHTTPS = false

// 上传是否使用CDN上传加速
cfg.UseCdnDomains = false

这里需要注意的是cfg.Zone,还记得之前添加资源的时候,选择的区域吗?

华东  storage.ZoneHuadong
华北  storage.ZoneHuabei
华南  storage.ZoneHuanan
北美  storage.ZoneBeimei

表单上传的额外可选项
// PutExtra 为表单上传的额外可选项

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

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

    // 上传事件:进度通知。这个事件的回调函数应该尽可能快地结束。
    OnProgress func(fsize,uploaded int64)
}

标准的上传回复内容
如果使用了上传回调或者自定义了returnBody,那么需要根据实际情况,自己自定义一个返回值结构体

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

表单上传的对象

FormUploader 表示一个表单上传的对象

type FormUploader struct { client *rpc.Client cfg *Config }

构建一个表单上传的对象

func NewFormUploader(cfg *Config) *FormUploader {
    if cfg == nil {
        cfg = &Config{}
    }

    return &FormUploader{
        client: &rpc.DefaultClient,cfg:    cfg,}
}

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

func (p *FormUploader) PutFile(
    ctx context.Context,ret interface{},uptoken,key,localFile string,extra *PutExtra) (err error) {
    return p.putFile(ctx,ret,true,localFile,extra)
}

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

实战

文件上传(表单方式)

直接上代码了,要把accessKey和secretKey换成你自己的!!!!

package main

import (
    "context"
    "fmt"

    "github.com/qiniu/api.v7/auth/qbox"
    "github.com/qiniu/api.v7/storage"
)

func main() {
    accessKey := "TgVGKnpCMLDI6hSS4rSWE3g-FZjMPf6Zbc******"
    secretKey := "zqZvH3fNVaggw00oc9wCrcWKgeeiV7WITF******"
    localFile := "1.png"
    bucket := "wangshubotest"
    key := "1.png"
    putPolicy := storage.PutPolicy{
        Scope: bucket,secretKey)
    upToken := putPolicy.UploadToken(mac)

    cfg := storage.Config{}
    cfg.Zone = &storage.ZoneHuadong
    cfg.UseHTTPS = false
    cfg.UseCdnDomains = false

    formUploader := storage.NewFormUploader(&cfg)
    ret := storage.PutRet{}

    putExtra := storage.PutExtra{
        Params: map[string]string{
            "x:name": "github logo",},}
    err := formUploader.PutFile(context.Background(),&ret,upToken,&putExtra)
    if err != nil {
        fmt.Println(err)
        return
    }
    fmt.Println(ret.Key,ret.Hash)
}

输出:
1.png FhR37vPVvgaAKJl56iaR5nLip-jM
登录七牛云,在内容管理中可以看到我们上传的文件

覆盖七牛云上已经存在的文件

我们想替换七牛云上1.png文件,我们重新选一个本地文件命名为1.png,然后执行上面的代码,结果输出:
file exists

那我们应该如何覆盖?
其实,很简单,我们要知道想要覆盖的文件名称,这里就是1.png

package main

import (
    "context"
    "fmt"

    "github.com/qiniu/api.v7/auth/qbox"
    "github.com/qiniu/api.v7/storage"
)

func main() {
    accessKey := "TgVGKnpCMLDI6hSS4rSWE3g-FZjMPf6Zbc******"
    secretKey := "zqZvH3fNVaggw00oc9wCrcWKgeeiV7WITF******"
    localFile := "1.png"
    bucket := "wangshubotest"
    key := "1.png"
    keyToOverwrite := "1.png"
    putPolicy := storage.PutPolicy{
        Scope: fmt.Sprintf("%s:%s",bucket,keyToOverwrite),secretKey)
    upToken := putPolicy.UploadToken(mac)

    cfg := storage.Config{}
    // 空间对应的机房
    cfg.Zone = &storage.ZoneHuadong
    // 是否使用https域名
    cfg.UseHTTPS = false
    // 上传是否使用CDN上传加速
    cfg.UseCdnDomains = false
    // 构建表单上传的对象
    formUploader := storage.NewFormUploader(&cfg)
    ret := storage.PutRet{}
    // 可选配置
    putExtra := storage.PutExtra{
        Params: map[string]string{
            "x:name": "github logo",ret.Hash)

}

我们可以看到,文件已经被覆盖。

上传文件自定义返回值结构体

之前的两段代码,上传文件的返回都是key和hash,我们是可以自己定义的,主要是设置ReturnBody:

package main

import (
    "context"
    "fmt"

    "github.com/qiniu/api.v7/auth/qbox"
    "github.com/qiniu/api.v7/storage"
)

// 自定义返回值结构体
type MyPutRet struct {
    Key    string
    Hash   string
    Fsize  int
    Bucket string
    Name   string
}

func main() {
    accessKey := "TgVGKnpCMLDI6hSS4rSWE3g-FZjMPf6Zbc******"
    secretKey := "zqZvH3fNVaggw00oc9wCrcWKgeeiV7WITF******"
    localFile := "1.png"
    bucket := "wangshubotest"
    key := "1.png"

    putPolicy := storage.PutPolicy{
        Scope:      bucket,ReturnBody: `{"key":"$(key)","hash":"$(etag)","fsize":$(fsize),"bucket":"$(bucket)","name":"$(x:name)"}`,secretKey)
    upToken := putPolicy.UploadToken(mac)

    cfg := storage.Config{}
    // 空间对应的机房
    cfg.Zone = &storage.ZoneHuadong
    // 是否使用https域名
    cfg.UseHTTPS = false
    // 上传是否使用CDN上传加速
    cfg.UseCdnDomains = false
    // 构建表单上传的对象
    formUploader := storage.NewFormUploader(&cfg)
    ret := MyPutRet{}
    // 可选配置
    putExtra := storage.PutExtra{
        Params: map[string]string{
            "x:name": "github logo",&putExtra)
    if err != nil {
        fmt.Println(err)
        return
    }
    fmt.Println(ret)

}

输出:
{1.png Fn616MXMfraD1V_u_TKIjC3X491Z 28540 wangshubotest github logo}

字节数组上传(表单方式)

这里用到的Put而不是PutFile。

Put 用来以表单方式上传一个文件。

func (p *FormUploader) Put(
    ctx context.Context,key string,data io.Reader,size int64,extra *PutExtra) (err error) {
    err = p.put(ctx,data,size,extra,path.Base(key))
    return
}

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

package main

import (
    "bytes"
    "context"
    "fmt"

    "github.com/qiniu/api.v7/auth/qbox"
    "github.com/qiniu/api.v7/storage"
)

// 自定义返回值结构体
type MyPutRet struct {
    Key    string
    Hash   string
    Fsize  int
    Bucket string
    Name   string
}

func main() {
    accessKey := "TgVGKnpCMLDI6hSS4rSWE3g-FZjMPf6Zbc******"
    secretKey := "zqZvH3fNVaggw00oc9wCrcWKgeeiV7WITF******"
    bucket := "wangshubotest"
    key := "2.log"

    putPolicy := storage.PutPolicy{
        Scope: bucket,secretKey)
    upToken := putPolicy.UploadToken(mac)

    cfg := storage.Config{}
    cfg.Zone = &storage.ZoneHuadong
    cfg.UseHTTPS = false
    cfg.UseCdnDomains = false
    formUploader := storage.NewFormUploader(&cfg)
    ret := MyPutRet{}
    // 可选配置
    putExtra := storage.PutExtra{
        Params: map[string]string{
            "x:name": "github logo",}
    data := []byte("welcome to the hotel")
    dataLen := int64(len(data))
    err := formUploader.Put(context.Background(),bytes.NewReader(data),dataLen,&putExtra)
    if err != nil {
        fmt.Println(err)
        return
    }
    fmt.Println(ret)

}

输出:
{2.log Fh3tNUEoiaj-qkNcP915nRuiAm4- 0 }

断点续传

断点续传,官方给出了完整了例子,这里就不贴代码了。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


类型转换 1、int转string 2、string转int 3、string转float 4、用户结构类型转换
package main import s "strings" import "fmt" var p = fmt.Println func main() { p("Contains: ", s.Contains("test&quo
类使用:实现一个people中有一个sayhi的方法调用功能,代码如下: 接口使用:实现上面功能,代码如下:
html代码: beego代码:
1、读取文件信息: 2、读取文件夹下的所有文件: 3、写入文件信息 4、删除文件,成功返回true,失败返回false
配置环境:Windows7+推荐IDE:LiteIDEGO下载地址:http://www.golangtc.com/downloadBeego开发文档地址:http://beego.me/docs/intro/ 安装步骤: 一、GO环境安装 二、配置系统变量 三、Beego安装 一、GO环境安装 根
golang获取程序运行路径:
Golang的文档和社区资源:为什么它可以帮助开发人员快速上手?
Golang:AI 开发者的实用工具
Golang的标准库:为什么它可以大幅度提高开发效率?
Golang的部署和运维:如何将应用程序部署到生产环境中?
高性能AI开发:Golang的优势所在
本篇文章和大家了解一下go语言开发优雅得关闭协程的方法。有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助。1.简介本文将介绍首先为什么需要主...
这篇文章主要介绍了Go关闭goroutine协程的方法,具有一定借鉴价值,需要的朋友可以参考下。下面就和我一起来看看吧。1.简介本文将介绍首先为什么需要主动关闭gor...
本篇文章和大家了解一下go关闭GracefulShutdown服务的几种方法。有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助。目录Shutdown方法Regi...
这篇文章主要介绍了Go语言如何实现LRU算法的核心思想和实现过程,具有一定借鉴价值,需要的朋友可以参考下。下面就和我一起来看看吧。GO实现Redis的LRU例子常
今天小编给大家分享的是Go简单实现多租户数据库隔离的方法,相信很多人都不太了解,为了让大家更加了解,所以给大家总结了以下内容,一起往下看吧。一定会...
这篇“Linux系统中怎么安装NSQ的Go语言客户端”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希
本文小编为大家详细介绍“怎么在Go语言中实现锁机制”,内容详细,步骤清晰,细节处理妥当,希望这篇“怎么在Go语言中实现锁机制”文章能帮助大家解决疑惑,下面...
今天小编给大家分享一下Go语言中interface类型怎么使用的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考