package oss import ( "bytes" "io" "github.com/aliyun/aliyun-oss-go-sdk/oss" ) func newSys(options Options) (sys *OSS, err error) { sys = &OSS{options: options} err = sys.Init() return } // NewPresigner 用显式凭证构建一个「只用于生成预签名 URL」的 OSS 句柄。 // // 与 newSys/Init 不同:不做 bucket 存在性检查、也不自动建桶——因为 // 1. 预签名是纯本地签名运算,不需要任何网络请求; // 2. 托管方(第三方服务配置里填的)AK/SK 往往只有读写对象的权限、没有建桶权限, // 走 Init 反而会 panic/报错。 // // 适合 console 按「选中应用」从 svc_config 动态读出凭证后即用即建(无状态、可每请求新建)。 func NewPresigner(endpoint, accessKeyId, accessKeySecret, bucketName string) (sys *OSS, err error) { sys = &OSS{options: Options{ Endpoint: endpoint, AccessKeyId: accessKeyId, AccessKeySecret: accessKeySecret, BucketName: bucketName, }} if sys.client, err = oss.New(endpoint, accessKeyId, accessKeySecret); err != nil { return nil, err } if sys.bucket, err = sys.client.Bucket(bucketName); err != nil { return nil, err } return sys, nil } // SignPutURL 生成一个供「浏览器直传(PUT)」用的预签名 URL,有效期 expiredSec 秒。 // // contentType 非空时会计入签名(OSS V1 签名字符串包含 Content-Type)——因此浏览器 PUT 时 // 必须带完全相同的 Content-Type 请求头,否则 OSS 返回 SignatureDoesNotMatch。 func (this *OSS) SignPutURL(objectName string, contentType string, expiredSec int64) (url string, err error) { if contentType != "" { return this.bucket.SignURL(objectName, oss.HTTPPut, expiredSec, oss.ContentType(contentType)) } return this.bucket.SignURL(objectName, oss.HTTPPut, expiredSec) } type OSS struct { options Options client *oss.Client bucket *oss.Bucket } func (this *OSS) Init() (err error) { if this.options.SecurityToken != "" { this.client, err = oss.New(this.options.Endpoint, this.options.AccessKeyId, this.options.AccessKeySecret, oss.SecurityToken(this.options.SecurityToken)) } else { this.client, err = oss.New(this.options.Endpoint, this.options.AccessKeyId, this.options.AccessKeySecret) } if err != nil { return err } if ok, err := this.client.IsBucketExist(this.options.BucketName); !ok || err != nil { if err = this.CreateBucket(this.options.BucketName); err == nil { this.bucket, err = this.client.Bucket(this.options.BucketName) return err } else { return err } } else { this.bucket, err = this.client.Bucket(this.options.BucketName) return err } } //创建存储空间。 func (this *OSS) CreateBucket(bucketName string) (err error) { err = this.client.CreateBucket(bucketName) return err } //上传文件 //上传文件到OSS时需要指定包含文件后缀在内的完整路径,例如abc/efg/123.jpg。 //由本地文件路径加文件名包括后缀组成,例如/users/local/myfile.txt。 func (this *OSS) UploadFile(objectName string, localFileName string) (err error) { err = this.bucket.PutObjectFromFile(objectName, localFileName) return err } //上传对象 // 上传文件到OSS时需要指定包含文件后缀在内的完整路径,例如abc/efg/123.jpg。 // 由本地文件路径加文件名包括后缀组成,例如/users/local/myfile.txt。 // 上传文件。 func (this *OSS) UploadObject(objectKey string, reader io.Reader, options ...oss.Option) (err error) { err = this.bucket.PutObject(objectKey, reader, options...) return err } //下载文件。 //从OSS下载文件时需要指定包含文件后缀在内的完整路径,例如abc/efg/123.jpg。 func (this *OSS) DownloadFile(objectName string, downloadedFileName string) (err error) { err = this.bucket.GetObjectToFile(objectName, downloadedFileName) return err } //下载文件到缓存 func (this *OSS) GetObject(objectName string, options ...oss.Option) ([]byte, error) { if file, err := this.bucket.GetObject(objectName, options...); err != nil { return nil, err } else { defer file.Close() buf := new(bytes.Buffer) if _, err := buf.ReadFrom(file); err != nil { return nil, err } else { return buf.Bytes(), nil } } } //复制文件 func (this *OSS) CopyObject(srcObjectKey, destObjectKey string, options ...oss.Option) (err error) { _, err = this.bucket.CopyObject(srcObjectKey, destObjectKey, options...) return } //删除文件 func (this *OSS) DeleteFile(objectName string, options ...oss.Option) (err error) { err = this.bucket.DeleteObject(objectName, options...) return } func (this *OSS) DeleteFiles(objectNames []string, options ...oss.Option) (err error) { _, err = this.bucket.DeleteObjects(objectNames, options...) return } //获取临时访问url func (this *OSS) GetURL(objectName string, expired int64, options ...oss.Option) (url string, err error) { url, err = this.bucket.SignURL(objectName, oss.HTTPGet, expired, options...) return }