• 干货 | 基于Go SDK操作京东云对象存储OSS的入门指南


    前言

    本文介绍如何使用Go语言对京东云对象存储OSS进行基本的操作,帮助客户快速通过Go SDK接入京东云对象存储,提高应用开发的效率。

    在实际操作之前,我们先看一下京东云OSS的API接口支持范围和能力。从对象存储的API文档可以看到,京东云提供两套接口:

    1、兼容S3 API,支持AWS S3接口,兼容大部分重要功能,作为后续重点开发和优化版本。由于并不是完全兼容S3的接口,因此需要重点阅读兼容接口列表,相关介绍见
    https://docs.jdcloud.com/cn/object-storage-service/compatibility-api-overview

    2、旧版OSS API,京东云前期独立封装的restful接口,支持基本的service、bucket、object等操作。该版本目前仍能使用,但后续不再开发。

    很明显,京东云提供兼容S3的接口,一方面可以快速支持原有基于AWS S3开发的应用程序,另一方面帮助客户的数据从AWS S3迁移过来。建议您使用兼容S3的接口,而同时京东云提供了丰富的多种语言版本的SDK,可以根据您项目开发的需要进行不同语言SDK的选择。
    相关介绍见

    https://docs.jdcloud.com/cn/object-storage-service/introduction-3

    这里需要注意查看兼容接口列表,对比京东云OSS和AWS S3接口的兼容情况。譬如Put Bucket接口仅使用通用的请求header,默认创建权限为private的bucket。由于不支持x-amz-acl, x-amz-grant-*等请求头,无法使用标准权限来设置ACL(即Canned ACL)。如果需要创建时指定bucket ACL,需要通过另外的接口实现,这个下文会提及。
    兼容接口列表:
    https://docs.jdcloud.com/cn/object-storage-service/compatibility-api-overview

    下面以Go SDK介绍京东云OSS的基本操作,实现对象资源的上传下载等功能。

    环境准备

    1、安装或更新Go 1.5及以上版本(参考1 - Mac下安装Go语言环境配置)。

    2、(可选)通过可视化IDE Atom搭建Go编译环境。相比于sublime text或者传统的vim编辑方式,Atom是更为先进的文本代码编辑器,是由Github打造的编程开发工具,除了界面美观,还有各种强大的插件。本文以Atom开发环境作为展示(参考2 – Mac下基于Atom构建Go开发环境)

    image

    3、在使用Go SDK发起请求之前,需提前在京东云用户中心账户管理下的AccessKey管理页面申请accesskey和secretKey密钥对(简称AK/SK)。这个秘钥对会在后续程序初始化使用到。

    下载和安装

    1、命令行安装
    go get github.com/aws/aws-sdk-go

    2、Atom安装(可选)
    菜单【Packages】-> 【Go】-> 【Get Package】,然后输入github.com/aws/aws-sdk-go,稍等片刻便下载和安装完成。代码会被下载到GOPATH环境变量中第一个路径src目录中,效果与命令行安装方法一样。

    image

    SDK组成概述

    在具体编码之前,建议了解AWS SDK的构成,主要包括SDK core和service clients两个部分。SDK core适用于所有AWS的服务,service中的client仅适用于对应的service,作为该服务的客户端进行调用。

    SDK core包括一些通用的类,帮助更容易地构造API参数,譬如Config、Logger等。其中,
    awserr:进程异常的接口,返回进程中遇到的异常和错误,对应错误码和信息。
    credential:API调用需要身份认证,需要使用京东云的AK/SK进行认证,并且需要修改默认的Config配置项。
    endpoints:服务的调用入口,有区域属性,需要在Config中配置。
    session:提供配置的初始化,可以自定义配置中的参数进行初始化,包括region、endpoints、credential等。
    request:提供API请求和重试,可以自定义请求及其处理方法。

    创建s3 client的示例
    在发起OSS(S3协议)的请求之前,需要初始化s3 client,以下为创建client的例子。

     1   ak := "your accesskey"
     2    sk := "your secretkey"
     3    token := "" //Token留空
     4    creds := credentials.NewStaticCredentials(ak, sk, token)
     5    _,err := creds.Get()
     6
     7    config := &aws.Config{
     8        Region:      aws.String("cn-north-1"),                 //Bucket所在Region
     9        Endpoint:    aws.String("s3.cn-north-1.jcloudcs.com"), //Bucket所在Endpoint
    10        DisableSSL      :aws.Bool(false),
    11        Credentials     :creds,
    12    }
    13    client := s3.New(session.New(config))
    

    创建完s3 client之后,就可以对bucket、object等oss资源进行请求操作了。下面分别介绍创建bucket、上传文件(PutObject、Upload)、分片上传文件进行demo展示。

    • 创建bucket空间

    目标:在京东云华北区创建一个名字为go-sdk-sample的bucket,并设置ACL为公有读私有写(public-read)。

    示例代码:

     1  package main
     2
     3  import (
     4    "fmt"
     5    "os"
     6    "github.com/aws/aws-sdk-go/aws"
     7    "github.com/aws/aws-sdk-go/aws/credentials"
     8    "github.com/aws/aws-sdk-go/aws/session"
     9    "github.com/aws/aws-sdk-go/service/s3"
    10)
    11
    12func main() {
    13    bucket := "go-sdk-sample"
    14    // Create S3 service client
    15    svc := s3.New(newSession())
    16
    17    crParams := &s3.CreateBucketInput{
    18        Bucket: aws.String(bucket),
    19    }
    20
    21    _, err := svc.CreateBucket(crParams)
    22
    23    if err != nil {
    24        exitErrorf("Unable to create bucket %q, %v", bucket, err)
    25    }
    26
    27    // Wait until bucket is created before finishing
    28    fmt.Printf("Waiting for bucket %q to be created...
    ", bucket)
    29
    30    err = svc.WaitUntilBucketExists(&s3.HeadBucketInput{
    31        Bucket: aws.String(bucket),
    32    })
    33    if err != nil {
    34        exitErrorf("Error occurred while waiting for bucket to be created, %v", bucket)
    35    }
    36
    37    fmt.Printf("Bucket %q successfully created
    ", bucket)
    38
    39    puParams := &s3.PutBucketAclInput{
    40        Bucket: aws.String(bucket),
    41    }
    42    puParams.SetACL("public-read") //set bucket ACL
    43
    44    _, err = svc.PutBucketAcl(puParams)
    45    if err != nil {
    46        exitErrorf(err.Error())
    47    }
    48    fmt.Println("Set", bucket, "ACL to public-read")
    49
    50}
    51
    52func newSession() *session.Session {
    53    ak := " your accesskey "
    54    sk := " your secretkey "
    55    token := "" //Token留空
    56
    57    creds := credentials.NewStaticCredentials(ak, sk, token)
    58    creds.Get()
    59
    60    config := &aws.Config{
    61        Region:      aws.String("cn-north-1"),                 //Bucket所在Region
    62        Endpoint:    aws.String("s3.cn-north-1.jcloudcs.com"), //Bucket所在Endpoint
    63        DisableSSL:  aws.Bool(false),
    64        Credentials: creds,
    65    }
    66    return session.New(config)
    67}
    68
    69func exitErrorf(msg string, args ...interface{}) {
    70    fmt.Fprintf(os.Stderr, msg+"
    ", args...)
    71    os.Exit(1)
    72}
    

    示例中可以看出,我们通过CreatBucket的接口创建bucket,并通过PutBucketAcl的接口设置bucket的ACL。目前京东云支持三种访问权限,包括私有读写(private)、公有读私有写(public-read)、公有读写(public-read-write)。

    执行结果:

    执行成功,控制台显示对应的bucket创建成功。

    • 上传文件(PutObject)

    目标:把一个object上传到bucket中,并加入MD5校验确保数据完整性。

    示例代码:

     1package main
     2
     3import (
     4    "crypto/md5"
     5    "encoding/hex"
     6    "fmt"
     7    "io"
     8    "os"
     9
    10    "github.com/aws/aws-sdk-go/aws"
    11    "github.com/aws/aws-sdk-go/aws/credentials"
    12    "github.com/aws/aws-sdk-go/aws/session"
    13    "github.com/aws/aws-sdk-go/service/s3"
    14)
    15
    16func main() {
    17    filename := "your file path" //file path
    18
    19    file, err := os.Open(filename)
    20    if err != nil {
    21        exitErrorf("Unable to open file %q, %v", err)
    22    }
    23    defer file.Close()
    24
    25    md5_file := CreateMd5(filename)
    26
    27    // Create S3 service client
    28    svc := s3.New(newSession())
    29
    30    input := &s3.PutObjectInput{
    31        Body:       file,
    32        Bucket:     aws.String("go-sdk-sample"),
    33        Key:        aws.String(filename),
    34        ContentMD5: aws.String(md5_file), //MD5 校验(可选)
    35    }
    36
    37    result, err := svc.PutObject(input)
    38
    39    if err != nil {
    40        exitErrorf("Put Object Error, %v", err)
    41    }
    42
    43    fmt.Println(result)
    44
    45}
    46// MD5校验
    47func CreateMd5(filename string) string {
    48
    49    f, err := os.Open(filename)
    50    if err != nil {
    51        exitErrorf("Unable to open file %q, %v", err)
    52    }
    53    defer f.Close()
    54
    55    md5hash := md5.New()
    56    io.Copy(md5hash, f)
    57
    58    return hex.EncodeToString(md5hash.Sum(nil))
    59
    60}
    61
    62func newSession() *session.Session {
    63    ak := " your accesskey "
    64    sk := " your secretkey "
    65    token := "" //Token留空
    66
    67    creds := credentials.NewStaticCredentials(ak, sk, token)
    68    creds.Get()
    69
    70    config := &aws.Config{
    71        Region:      aws.String("cn-north-1"),                 //Bucket所在Region
    72        Endpoint:    aws.String("s3.cn-north-1.jcloudcs.com"), //Bucket所在Endpoint
    73        DisableSSL:  aws.Bool(false),
    74        Credentials: creds,
    75    }
    76    return session.New(config)
    77}
    78
    79func exitErrorf(msg string, args ...interface{}) {
    80    fmt.Fprintf(os.Stderr, msg+"
    ", args...)
    81    os.Exit(1)
    82}
    

    示例中可以看出,我们通过PutObject接口上传本地文件,同时为了校验数据的准确性,加入了CreateMd5方法生成文件的MD5值,并传参到ContentMD5中,OSS服务端会校验文件,如果为相同值会返回成功的result,即文件的ETAG值。

    执行结果:

    可以从控制台看到文件已经正确上传,ETag与文件计算的MD5值相符。可以尝试修改ContentMD5的参数为其他值,会返回错误结果,这里就不具体展示了。

    • 上传文件(Uploader)

    上面通过PutObject的方法进行文件上传,那么如果文件比较大,一般通过分片上传的方式来实现分块、并发和重试机制,确保大,文件的上传。这里需要用到CreateMultipartUpload、UploadPart、CompletedPart、AbortMultipartUpload等多个接口来完成整个过程,同时需要自行实现重试、并行等逻辑,相对比较复杂。S3提供了S3 Upload Manager来帮助用户实现以上逻辑,能够自动判断文件大小来选择单次上传或分块上传的方式来完成。同时,用户可以自定义块大小(PartSize)、并发数(Concurrency)以及最大块数量(MaxUploadParts)等参数,满足不同场景的需要。

    示例代码:

     1package main
     2
     3import (
     4    "fmt"
     5    "os"
     6
     7    "github.com/aws/aws-sdk-go/aws"
     8    "github.com/aws/aws-sdk-go/aws/credentials"
     9    "github.com/aws/aws-sdk-go/aws/session"
    10    "github.com/aws/aws-sdk-go/service/s3/s3manager"
    11)
    12
    13func main() {
    14    bucket := " go-sdk-sample "                                   //bucket name
    15    filename := " your file path " //file url
    16
    17    file, err := os.Open(filename)
    18    if err != nil {
    19        exitErrorf("Unable to open file %q, %v", err)
    20    }
    21    defer file.Close()
    22
    23    sess := newSession()
    24    uploader := s3manager.NewUploader(sess)
    25
    26    upParams := &s3manager.UploadInput{
    27        Bucket: aws.String(bucket),
    28        Key:    aws.String(filename),
    29        Body:   file,
    30    }
    31
    32    //
    33    result, err := uploader.Upload(upParams, func(u *s3manager.Uploader) {
    34        u.PartSize = 10 * 1024 * 1024  //自定义分块大小,10M每个分片
    35        u.LeavePartsOnError = true     //true,上传出错会保留已成功上传的分块
    36        u.Concurrency = 3             //定义并发数,即goroutines数量
    37        u.MaxUploadParts = 10000      //定义最大可上传块数量
    38    })
    39
    40    if err != nil {
    41        exitErrorf("Put Object Error, %v", err)
    42    }
    43
    44    fmt.Printf("Successfully uploaded!
    ")
    45    fmt.Println("File URL: " + result.Location)
    46}
    47
    48func newSession() *session.Session {
    49    ak := " your accesskey "
    50    sk := " your secretkey "
    51    token := "" //Token留空
    52
    53    creds := credentials.NewStaticCredentials(ak, sk, token)
    54    creds.Get()
    55
    56    config := &aws.Config{
    57        Region:      aws.String("cn-north-1"),                 //Bucket所在Region
    58        Endpoint:    aws.String("s3.cn-north-1.jcloudcs.com"), //Bucket所在Endpoint
    59        DisableSSL:  aws.Bool(false),
    60        Credentials: creds,
    61    }
    62    return session.New(config)
    63}
    64
    65func exitErrorf(msg string, args ...int,erface{}) {
    66    fmt.Fprintf(os.Stderr, msg+"
    ", args...)
    67    os.Exit(1)
    68}
    

    可以看到,与前面PutObject不同,这里使用s3manager.NewUploader来构造上传服务,通过uploader.Upload方法上传文件。Upload的具体实现逻辑可以参考源码:

    https://github.com/aws/aws-sdk-go/blob/master/service/s3/s3manager/upload.go

    譬如自动判断是否分块上传的逻辑如下:

    执行结果:

    本次上传的文件大小为16M,比PartSize的10M大,因此会执行分块上传。在上传过程中,可以在控制台-分片管理看到对应正在上传的分片任务,说明正在分片上传。upload的上传成功后会返回文件访问地址location。

    至此,我们已经把主要的OSS操作示例介绍完毕,其余的操作我们根据实际需要继续整理,譬如不使用s3manager,直接用MultipartUpload等基础接口来实现分块上传,大家可以尝试一下,我们下回分解。


    参考1:Mac下安装Go语言环境配置

    1、安装Go
    使用brew进行安装,brew是Mac下的一个包管理工具,类似于CentOS下的 yum,可以很方便地进行安装、卸载和更新各种软件包。
    brew install go

    安装后在终端输入go version查看安装的版本,我的显示go version go1.12.5 darwin/amd64,表示安装的是v1.12.5版本。

    2、配置环境变量
    查看go的环境变量设置
    go env

    参考2:Mac下基于Atom构建Go开发环境

    1、安装Atom
    https://atom.io/ Atom官网,可以直接下载软件安装。

    2、安装Go语言环境(参考1的步骤)

    3、安装go-plus插件
    go-plus是Atom上面的一款开源的Golang开发环境插件,项目地址:
    https://github.com/joefitzgerald/go-plus

    在Atom中的Preference中可以找到install菜单,输入go-plus。

    点击:install,就会开始安装go-plus,go-plus插件会自动安装对应的依赖插件,如果没有安装对应的Golang类库可以使用go get安装。

    安装完我们就可以进行编码,为了方便编译、测试和编译,需要配合terminal使用,可以通过view-Terminal打开终端,不需要另外切换界面。

    go-plus有非常多的特性,能够实时反馈语法错误和编译错误。每保存一个文件,go-plus就会在后台运行你提前配置好的要执行的go tools,例如:go vet、 go oracle、go build等等,然后将错误和警告在编辑器底部显示出来。

    go-plus同样能够在编辑器的对应行上显示该行的编译错误提示和错误信息,这样你就能很快的定位哪一行有错。大家可以尝试一下。

    欢迎点击“链接”了解更多精彩内容

    阅读原文

  • 相关阅读:
    深入浅出WPF-08.Event( 事件)01
    深入浅出WPF-07.Property(属性)
    深入浅出WPF-06.Binding(绑定)03
    深入浅出WPF-06.Binding(绑定)02
    深入浅出WPF-06.Binding(绑定)01
    常用快递电子面单账户申请详解(顺丰、中通、圆通、申通、百世、韵达)
    快递鸟电子面单批量打印以及模板设置
    快递公司电子面单怎么申请充值单号(中通、圆通、申通、韵达、百世)
    不限量的快递鸟单号查询接口-JAVA对接方法
    快递单号识别查询api接口调用对接demo
  • 原文地址:https://www.cnblogs.com/jdclouddeveloper/p/10979341.html
Copyright © 2020-2023  润新知