mirror of https://github.com/go-sonic/sonic.git
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
175 lines
5.7 KiB
Go
175 lines
5.7 KiB
Go
package filestorageimpl
|
|
|
|
import (
|
|
"context"
|
|
"image"
|
|
"io"
|
|
"mime/multipart"
|
|
"net/url"
|
|
|
|
"github.com/aliyun/aliyun-oss-go-sdk/oss"
|
|
|
|
"github.com/go-sonic/sonic/consts"
|
|
"github.com/go-sonic/sonic/model/dto"
|
|
"github.com/go-sonic/sonic/model/property"
|
|
"github.com/go-sonic/sonic/service"
|
|
"github.com/go-sonic/sonic/util/xerr"
|
|
)
|
|
|
|
type Aliyun struct {
|
|
OptionService service.OptionService
|
|
}
|
|
|
|
func NewAliyun(optionService service.OptionService) *Aliyun {
|
|
return &Aliyun{
|
|
OptionService: optionService,
|
|
}
|
|
}
|
|
|
|
type aliyunClient struct {
|
|
*oss.Client
|
|
Bucket *oss.Bucket
|
|
BucketName string
|
|
EndPoint string
|
|
Source string
|
|
Style string
|
|
ThubmnailStyle string
|
|
Domain string
|
|
Protocol string
|
|
}
|
|
|
|
func (a *Aliyun) Upload(ctx context.Context, fileHeader *multipart.FileHeader) (*dto.AttachmentDTO, error) {
|
|
aliyunClientInstance, err := a.getAliOSSClient(ctx)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
basePath := aliyunClientInstance.Protocol + aliyunClientInstance.BucketName + "." + aliyunClientInstance.EndPoint
|
|
if aliyunClientInstance.Domain != "" {
|
|
basePath = aliyunClientInstance.Protocol + aliyunClientInstance.Domain
|
|
}
|
|
fd, err := newURLFileDescriptor(
|
|
withBaseURL(basePath),
|
|
withSubURLPath(aliyunClientInstance.Source),
|
|
withShouldRenameURLOption(commonRenamePredicateFunc(ctx, consts.AttachmentTypeAliOSS)),
|
|
withOriginalNameURLOption(fileHeader.Filename),
|
|
)
|
|
if err != nil {
|
|
return nil, xerr.WithStatus(err, xerr.StatusInternalServerError)
|
|
}
|
|
file, err := fileHeader.Open()
|
|
if err != nil {
|
|
return nil, xerr.WithStatus(err, xerr.StatusInternalServerError).WithMsg("open upload file error")
|
|
}
|
|
defer file.Close()
|
|
err = aliyunClientInstance.Bucket.PutObject(fd.getRelativePath(), file)
|
|
if err != nil {
|
|
return nil, xerr.WithMsg(err, "upload to aliyun oss error: "+err.Error()).WithStatus(xerr.StatusInternalServerError)
|
|
}
|
|
mediaType, _ := getFileContentType(file)
|
|
result := &dto.AttachmentDTO{
|
|
Name: fd.getFileName(),
|
|
Path: fd.getRelativePath() + aliyunClientInstance.Style,
|
|
FileKey: fd.getRelativePath(),
|
|
Suffix: fd.getExtensionName(),
|
|
MediaType: mediaType,
|
|
AttachmentType: consts.AttachmentTypeAliOSS,
|
|
Size: fileHeader.Size,
|
|
}
|
|
_, err = file.Seek(0, io.SeekStart)
|
|
if err != nil {
|
|
return nil, xerr.WithStatus(err, xerr.StatusInternalServerError)
|
|
}
|
|
err = handleImageMeta(file, result, func(_ image.Image) (string, error) {
|
|
if aliyunClientInstance.ThubmnailStyle != "" {
|
|
return fd.getRelativePath() + aliyunClientInstance.ThubmnailStyle, nil
|
|
} else {
|
|
return fd.getRelativePath(), nil
|
|
}
|
|
})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return result, nil
|
|
}
|
|
|
|
func (a *Aliyun) Delete(ctx context.Context, fileKey string) error {
|
|
aliyunClientInstance, err := a.getAliOSSClient(ctx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
err = aliyunClientInstance.Bucket.DeleteObject(fileKey)
|
|
if err != nil {
|
|
return xerr.WithMsg(err, "delete file err from aliyun oss").WithStatus(xerr.StatusInternalServerError)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (a *Aliyun) GetAttachmentType() consts.AttachmentType {
|
|
return consts.AttachmentTypeAliOSS
|
|
}
|
|
|
|
func (a *Aliyun) GetFilePath(ctx context.Context, relativePath string) (string, error) {
|
|
aliyunClientInstance, err := a.getAliOSSClient(ctx)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
basePath := aliyunClientInstance.Protocol + aliyunClientInstance.BucketName + "." + aliyunClientInstance.EndPoint
|
|
if aliyunClientInstance.Domain != "" {
|
|
basePath = aliyunClientInstance.Protocol + aliyunClientInstance.Domain
|
|
}
|
|
fullPath, _ := url.JoinPath(basePath, relativePath)
|
|
fullPath, _ = url.PathUnescape(fullPath)
|
|
return fullPath, nil
|
|
}
|
|
|
|
func (a *Aliyun) getAliOSSClient(ctx context.Context) (*aliyunClient, error) {
|
|
getClientProperty := func(propertyValue *string, property property.Property, e error) error {
|
|
if e != nil {
|
|
return e
|
|
}
|
|
value, err := a.OptionService.GetOrByDefaultWithErr(ctx, property, property.DefaultValue)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
strValue, ok := value.(string)
|
|
if !ok {
|
|
return xerr.WithStatus(nil, xerr.StatusBadRequest).WithErrMsgf("wrong property type")
|
|
}
|
|
*propertyValue = strValue
|
|
return nil
|
|
}
|
|
var endPoint, bucketName, accessKey, accessSecret, source, styleRule, thumbnailStyleRule, domain, protocol string
|
|
err := getClientProperty(&endPoint, property.AliOssEndpoint, nil)
|
|
err = getClientProperty(&bucketName, property.AliOssBucketName, err)
|
|
err = getClientProperty(&accessKey, property.AliOssAccessKey, err)
|
|
err = getClientProperty(&accessSecret, property.AliOssAccessSecret, err)
|
|
err = getClientProperty(&source, property.AliOssSource, err)
|
|
err = getClientProperty(&styleRule, property.AliOssStyleRule, err)
|
|
err = getClientProperty(&thumbnailStyleRule, property.AliOssThumbnailStyleRule, err)
|
|
err = getClientProperty(&domain, property.AliOssDomain, err)
|
|
err = getClientProperty(&protocol, property.AliOssProtocol, err)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
client, err := oss.New(endPoint, accessKey, accessSecret, oss.Timeout(2, 60), oss.EnableCRC(true))
|
|
if err != nil {
|
|
return nil, xerr.WithStatus(err, xerr.StatusInternalServerError).WithMsg("failed to initialize aliyun oss client: " + err.Error())
|
|
}
|
|
aliyunClientInstance := &aliyunClient{}
|
|
aliyunClientInstance.Client = client
|
|
aliyunClientInstance.Source = source
|
|
aliyunClientInstance.BucketName = bucketName
|
|
aliyunClientInstance.EndPoint = endPoint
|
|
aliyunClientInstance.ThubmnailStyle = thumbnailStyleRule
|
|
aliyunClientInstance.Style = styleRule
|
|
aliyunClientInstance.Domain = domain
|
|
aliyunClientInstance.Protocol = protocol
|
|
aliyunClientInstance.Bucket, err = client.Bucket(bucketName)
|
|
if err != nil {
|
|
return nil, xerr.WithStatus(err, xerr.StatusInternalServerError).WithMsg("failed to initialize aliyun oss client bucket: " + err.Error())
|
|
}
|
|
return aliyunClientInstance, nil
|
|
}
|