s3文档
https://docs.aws.amazon.com/zh_cn/s3/?id=docs_gateway
s3 sdk for go文档:
https://docs.aws.amazon.com/zh_cn/sdk-for-go/index.html
只要会话没有被修改,会话就可以安全地并发使用。创建会话后,SDK 不会修改会话。从共享会话同时创建服务客户端是安全的。
创建服务客户端时,可以传入自定义配置,这样就不需要为每个配置创建会话。SDK 合并这两个配置,用您的自定义配置覆盖会话值。例如,在以下代码段中,Amazon S3 客户端使用 会话,但使用自定义值 ( )mySession覆盖该字段:Regionus-west-2
svc := s3.New(mySession, aws.NewConfig().WithRegion("us-west-2"))
一些 API 操作返回一个响应结构,其中包含Body一个 io.ReadCloser.请务必 Close。
resp, err := s3svc.GetObject(&s3.GetObjectInput{...})
if err != nil {
// handle error
return
}
// Make sure to always close the response Body when finished
defer resp.Body.Close()
decoder := json.NewDecoder(resp.Body)
if err := decoder.Decode(&myStruct); err != nil {
// handle error
return
}
您可以创建同时使用同一个服务客户端发送多个请求的 goroutine。您可以根据需要使用带有任意数量的 goroutine 的服务客户端。但是,您不能同时修改服务客户端的配置和请求处理程序。如果这样做,服务客户端操作可能会遇到竞争条件。在同时使用服务客户端之前定义它。
注意点:
S3ForcePathStyle: aws.Bool(false), 设置为false,使用virtual hosted style ,而不是pathstyle。
使用说明参考:2、使用S3协议访问OSS
比较OSS对象的MD5值和文件MD5值
package main
import (
"context"
"crypto/md5"
"encoding/hex"
"fmt"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/credentials"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/s3"
"io/ioutil"
"strings"
"time"
)
var (
accessKey = "xxx" //""
secretKey = "xxx" //""
region = "oss-cn-beijing"
endpoint = "oss-cn-beijing.aliyuncs.com"
timeout time.Duration = time.Second * 5
)
func main() {
sess, err := session.NewSession(&aws.Config{
Credentials: credentials.NewStaticCredentials(accessKey, secretKey, ""),
Endpoint: aws.String(endpoint),
Region: aws.String(region),
//minio:true,oss:false
S3ForcePathStyle: aws.Bool(false),
})
if err != nil {
panic(err)
}
svc := s3.New(sess)
//比较OSS对象中的MD5和自己生成的MD5值
compareMD5(svc, "bkt-bj1", "1.jpg")
}
func compareMD5(svc *s3.S3, bucket, key string) {
ctx, cancelFn := context.WithTimeout(context.Background(), timeout)
if cancelFn != nil {
defer cancelFn()
}
object, err := svc.GetObjectWithContext(ctx, &s3.GetObjectInput{
Bucket: aws.String(bucket),
Key: aws.String(key),
})
if err != nil {
panic(err)
}
fmt.Println("object.ETag:", *object.ETag)
fmt.Printf("object:%+v\n", object)
defer object.Body.Close()
all, err := ioutil.ReadAll(object.Body)
if err != nil {
panic(err)
}
myFileMD5 := md5Encode(all)
//OSS 的MD5为大写,ETag字符串两边带有双引号,比较前去掉"
ossObjectMD5 := strings.Trim(*object.ETag, "\"")
fmt.Println("myFileMD5:", myFileMD5)
fmt.Println("ossObjectMD5:", ossObjectMD5)
fmt.Println(strings.ToLower(ossObjectMD5) == myFileMD5)
}
// MD5加密
func md5Encode(arg0 []byte) string {
h := md5.New()
h.Write(arg0)
cipherStr := h.Sum(nil)
// 输出加密结果
return strings.ToLower(hex.EncodeToString(cipherStr))
}
输出结果
object.ETag: "9AFE56527B03F0391E268A976AB48E1E"
object:{
AcceptRanges: "bytes",
Body: buffer(0xc000384080),
ContentLength: 391703,
ContentType: "image/jpeg",
ETag: "\"9AFE56527B03F0391E268A976AB48E1E\"",
LastModified: 2022-07-26 01:41:24 +0000 UTC,
StorageClass: "STANDARD"
}
myFileMD5: 9afe56527b03f0391e268a976ab48e1e
ossObjectMD5: 9AFE56527B03F0391E268A976AB48E1E
true