乾貨 | 基於Go SDK操做京東雲對象存儲OSS的入門指南

前言

本文介紹如何使用Go語言對京東雲對象存儲OSS進行基本的操做,幫助客戶快速經過Go SDK接入京東雲對象存儲,提升應用開發的效率。git

在實際操做以前,咱們先看一下京東雲OSS的API接口支持範圍和能力。從對象存儲的API文檔能夠看到,京東雲提供兩套接口:github

一、兼容S3 API,支持AWS S3接口,兼容大部分重要功能,做爲後續重點開發和優化版本。因爲並非徹底兼容S3的接口,所以須要重點閱讀兼容接口列表,相關介紹見
https://docs.jdcloud.com/cn/object-storage-service/compatibility-api-overview編程

二、舊版OSS API,京東雲前期獨立封裝的restful接口,支持基本的service、bucket、object等操做。該版本目前仍能使用,但後續再也不開發。vim

很明顯,京東雲提供兼容S3的接口,一方面能夠快速支持原有基於AWS S3開發的應用程序,另外一方面幫助客戶的數據從AWS S3遷移過來。建議您使用兼容S3的接口,而同時京東雲提供了豐富的多種語言版本的SDK,能夠根據您項目開發的須要進行不一樣語言SDK的選擇。
相關介紹見api

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

這裏須要注意查看兼容接口列表,對比京東雲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-overviewsession

下面以Go SDK介紹京東雲OSS的基本操做,實現對象資源的上傳下載等功能。併發

環境準備

一、安裝或更新Go 1.5及以上版本(參考1 - Mac下安裝Go語言環境配置)。oracle

二、(可選)經過可視化IDE Atom搭建Go編譯環境。相比於sublime text或者傳統的vim編輯方式,Atom是更爲先進的文本代碼編輯器,是由Github打造的編程開發工具,除了界面美觀,還有各類強大的插件。本文以Atom開發環境做爲展現(參考2 – Mac下基於Atom構建Go開發環境)編輯器

image

三、在使用Go SDK發起請求以前,需提早在京東雲用戶中心帳戶管理下的AccessKey管理頁面申請accesskey和secretKey密鑰對(簡稱AK/SK)。這個祕鑰對會在後續程序初始化使用到。

下載和安裝

一、命令行安裝
go get github.com/aws/aws-sdk-go

二、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...\n", 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\n", 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+"\n", 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+"\n", 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!\n")
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+"\n", 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語言環境配置

一、安裝Go
使用brew進行安裝,brew是Mac下的一個包管理工具,相似於CentOS下的 yum,能夠很方便地進行安裝、卸載和更新各類軟件包。
brew install go

安裝後在終端輸入go version查看安裝的版本,個人顯示go version go1.12.5 darwin/amd64,表示安裝的是v1.12.5版本。

二、配置環境變量
查看go的環境變量設置
go env

參考2:Mac下基於Atom構建Go開發環境

一、安裝Atom
https://atom.io/ Atom官網,能夠直接下載軟件安裝。

二、安裝Go語言環境(參考1的步驟)

三、安裝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一樣可以在編輯器的對應行上顯示該行的編譯錯誤提示和錯誤信息,這樣你就能很快的定位哪一行有錯。你們能夠嘗試一下。

歡迎點擊「連接」瞭解更多精彩內容

閱讀原文

相關文章
相關標籤/搜索