前言

本文介绍如何使用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开发环境)

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目录中,效果与命令行安装方法一样。

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语言环境配置

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

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

阅读原文

干货 | 基于Go SDK操作京东云对象存储OSS的入门指南的更多相关文章

  1. TiKV 在京东云对象存储元数据管理的实践

    京东云对象存储是在 2016 年作为公有云对外公开的,主要特点是可靠.安全.海量.低成本,应用于包括一些常用的业务场景,比如京东内部的京东商城视频/图片云存储,面向京东云公有云外部的开发者的服务,和面 ...

  2. Delphi阿里云对象存储OSS【支持上传文件、下载文件、删除文件、创建目录、删除目录、Bucket操作等】

    作者QQ:(648437169) 点击下载➨Delphi阿里云对象存储OSS             阿里云api文档 [Delphi阿里云对象存储OSS]支持 获取Bucket列表.设置Bucket ...

  3. 阿里云对象存储OSS与文件存储NAS的区别

    一.简介 应用场景:选择一款存储产品,面向文档数据的存取,不会涉及到数据处理. 产品选型主要从OSS和NAS中选择一款,满足文档存储的需求. 二.NAS优缺点 NAS 是一种采用直接与网络介质相连的特 ...

  4. 阿里云对象存储OSS支持版本管理特性

    阿里云对象存储OSS现已经全面支持“对象版本管理”特性.该功能适用于所有的存储类型以及区域.当Bucket启用该特性后,“对象版本管理”功能可以保护和恢复误删除.误覆盖的数据. 对象存储OSS“版本管 ...

  5. 阿里云对象存储OSS访问控制

    阿里云对象存储OSS的Android SDK提供了STS鉴权模式和自签名模式来保障移动终端的安全性. OSS可以通过阿里云STS (Security Token Service) 进行临时授权访问.交 ...

  6. 阿里云对象存储OSS

    阿里云的产品种类繁多,今天让我们一起来了解下对象存储(Object Storage Service,简称OSS)吧! 什么是对象存储呢? 简单来说,对象存储OSS是阿里云提供的海量.安全和高可靠的云存 ...

  7. 阿里云对象存储OSS使用 HTTPS

    一.前言 阿里云对象存储oss本身也是可以用HTTPS直接访问的,但是它本身的地址是http://***.oss-cn-hangzhou.aliyuncs.com这样的,那么如果我们想使用自己的域名, ...

  8. 阿里云对象存储OSS及CDN加速配置

    目录 十大云存储服务商 1. 登陆阿里云官网,开通对象存储服务 OSS 2. 创建存储空间 3. 绑定自定义域名 4. 配置阿里云CDN加速 5. 购买阿里云免费SSL证书 6. 阿里云CDN配置HT ...

  9. java开发之阿里云对象存储OSS和云数据库Memcache的使用

    web开发中标配:aliyun ECS(阿里云服务器),aliyun RDS(阿里云数据库),aliyun OSS(阿里云对象存储),aliyun Memcache(阿里云缓存数据库). 今天就介绍下 ...

随机推荐

  1. 1.Maven分模块,分工程管理,多Web应用合并war包

    Eclipse 创建Maven工程 修改POM文件   Eclipse 创建Module工程 以此类推,创建Maven 的Modules web工程goodsmgrweb,创建Maven的Module ...

  2. MS SQLSERVER 自增ID列竟然会重复

    MS SQLSERVER 2008 R2 datacenter edition 自增的ID列,设为了主键. 从没遇到过的情况.

  3. python假设一段楼梯共 n(n>1)个台阶,小朋友一步最多能上 3 个台阶,那么小朋友上这段楼 梯一共有多少种方法

    我们先把前四节种数算出来(自己想是哪几类,如果你不会算,那就放弃写代码吧,干一些在街上卖肉夹馍的小生意,也挣得不少) 标号 1    2    3     4 种类 1    2    4     7 ...

  4. LeetCode1046 最后一块石头的重量(贪心—Java优先队列简单应用)

    题目: 有一堆石头,每块石头的重量都是正整数. 每一回合,从中选出两块最重的石头,然后将它们一起粉碎.假设石头的重量分别为 x 和 y,且 x <= y.那么粉碎的可能结果如下: 如果 x == ...

  5. UVA - 10305 Ordering Tasks(拓扑排序)

    题意:给定优先关系进行拓扑排序. 分析:将入度为0的点加入优先队列,并将与之相连的点入度减1,若又有度数为0的点,继续加入优先队列,依次类推. #pragma comment(linker, &quo ...

  6. WTL之VS2013环境搭建

    新版博客已经搭建好了,有问题请访问 htt://www.crazydebug.com 从国外回来,在老家入职了新公司,做c++开发,刚到新公司要熟悉公司的项目代码,目前公司在做一个主播聚合平台,界面采 ...

  7. springcloud--ribbo(负载均衡)

    ribbo:是Netflix公司开源的一个负载均衡的项目,是一个客户端负载均衡器,运行在客户端上. 实际运用案例(基于springcloud入门案例): 一.新建Module:springcloud- ...

  8. 068-PHP定义并输出数组

    <?php $arr=array(98,'hello',67,'A',85,NULL); //定义一个数组 echo "输出第一个元素:{$arr[0]}"; //输出数组的 ...

  9. [题解] LuoguP4827 [国家集训队] Crash 的文明世界

    传送门 这个题......我谔谔 首先可以考虑换根\(dp\),但到后来发现二项式定理展开过后需要维护\(k\)个值,同时每个值也要\(O(k)\)的时间按二项式定理算 当然fft优化过后就是k lo ...

  10. 逆向-PE导入表

    导入表 动态链接库需要导入表 结构 typedef struct _IMAGE_IMPORT_DESCRIPTOR { union { DWORD Characteristics; // 0 for ...