fusenapi/utils/file/upload.go
2023-11-23 15:37:48 +08:00

353 lines
8.3 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package file
import (
"bytes"
"context"
"fusenapi/model/gmodel"
"fusenapi/utils/basic"
"io"
"net/http"
"time"
"github.com/aliyun/aliyun-oss-go-sdk/oss"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/request"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/s3"
"github.com/zeromicro/go-zero/core/logx"
"gorm.io/gorm"
)
type Upload struct {
Ctx context.Context
MysqlConn *gorm.DB
AwsSession *session.Session
UploadType string
AliyunOSS AliyunOSS
}
type AliyunOSS struct {
Endpoint string `json:"endpoint"`
AccessKeyId string `json:"access_key_id"`
AccessKeySecret string `json:"access_key_secret"`
BucketName string `json:"bucket_name"`
BucketUrl string `json:"bucket_url"`
BasePath string `json:"base_path"`
}
type UploadBaseReq struct {
ResourceId string `json:"resource_id"`
Refresh int64 `json:"refresh"`
Source string `json:"source"`
FileHash string `json:"file_hash"`
FileData string `json:"file_data"`
Metadata string `json:"metadata"`
UploadBucket int64 `json:"upload_bucket"`
ApiType int64 `json:"api_type"`
UserId int64 `json:"user_id"`
GuestId int64 `json:"guest_id"`
FileByte []byte `json:"file_byte"`
}
type UploadBaseRes struct {
Key string `json:"key"`
Status int64 `json:"status"`
ApiType int64 `json:"api_type"`
ResourceId string `json:"resource_id"`
ResourceType string `json:"resource_type"`
ResourceUrl string `json:"resource_url"`
}
func (upload *Upload) UploadFileByBase64(req *UploadBaseReq) (*UploadBaseRes, error) {
var metadataB []byte
if req.Metadata != "" {
metadataB = []byte(req.Metadata)
}
// 定义存储桶名称
var bucketName *string
var apiType int64 = req.ApiType
// 根据类别选择存储桶
switch req.UploadBucket {
case 2:
bucketName = basic.TempfileBucketName
case 3:
bucketName = basic.StorageBucketName
default:
bucketName = basic.StorageBucketName
}
// 设置AWS会话的区域
upload.AwsSession.Config.Region = aws.String("us-east-2")
// 创建新的S3服务实例
svc := s3.New(upload.AwsSession)
// 定义S3请求和当前时间
var s3req *request.Request
var resourceId string = req.FileHash
var uploadBaseRes = UploadBaseRes{}
// 是否强制刷新
var refresh bool
if req.ResourceId != "" {
resourceId = req.ResourceId
}
if req.Refresh == 1 {
refresh = true
}
err := upload.MysqlConn.Transaction(func(tx *gorm.DB) (err error) {
var resourceInfo *gmodel.FsResource
if !refresh {
err = tx.Where("resource_id =?", resourceId).Take(&resourceInfo).Error
if err == nil && resourceInfo.ResourceId != "" {
uploadBaseRes.Status = 1
uploadBaseRes.ResourceId = resourceId
uploadBaseRes.ResourceUrl = *resourceInfo.ResourceUrl
} else {
refresh = true
}
}
if refresh {
dist, contentType, err := FileBase64ToByte(req.FileData)
if err != nil {
logx.Errorf("err:%+vdesc:%+v", err, "fail.upload.resourceInfoGet.mysql")
return err
}
// 创建S3对象存储请求
s3req, _ = svc.PutObjectRequest(
&s3.PutObjectInput{
Bucket: bucketName,
Key: &resourceId,
CacheControl: aws.String("no-cache"),
},
)
// 设置请求体为文件数据
s3req.SetBufferBody(dist)
// 发送请求
err = s3req.Send()
// 检查是否有错误
if err != nil {
logx.Errorf("err:%+vdesc:%+v", err, "fail.upload.s3req")
return err
} else {
var url = s3req.HTTPRequest.URL.String()
// 打印请求URL
// logx.Info(url)
uploadBaseRes.Status = 1
uploadBaseRes.ResourceId = resourceId
uploadBaseRes.ResourceUrl = url
var version string = "0.0.1"
var nowTime = time.Now().UTC()
var dbData = gmodel.FsResource{
ResourceId: resourceId,
UserId: &req.UserId,
GuestId: &req.GuestId,
ResourceType: &contentType,
ResourceUrl: &url,
Version: &version,
UploadedAt: &nowTime,
Metadata: &metadataB,
ApiType: &apiType,
BucketName: bucketName,
Source: &req.Source,
}
if refresh {
err = tx.Save(&dbData).Error
} else {
err = tx.Create(&dbData).Error
}
if err != nil {
logx.Errorf("err:%+vdesc:%+v", err, "fail.upload.resourceInfoAdd.mysql")
return err
}
}
}
// 返回 nil 提交事务
return nil
})
if err != nil {
return nil, err
}
return &uploadBaseRes, err
}
func (upload *Upload) UploadFileByByte(req *UploadBaseReq) (*UploadBaseRes, error) {
var metadataB []byte
if req.Metadata != "" {
metadataB = []byte(req.Metadata)
}
// 定义存储桶名称
var bucketName *string
var apiType int64 = req.ApiType
// 根据类别选择存储桶
switch req.UploadBucket {
case 2:
bucketName = basic.TempfileBucketName
case 3:
bucketName = basic.StorageBucketName
default:
bucketName = basic.StorageBucketName
}
// 设置AWS会话的区域
upload.AwsSession.Config.Region = aws.String("us-east-2")
// 创建新的S3服务实例
svc := s3.New(upload.AwsSession)
// 定义S3请求和当前时间
var s3req *request.Request
var resourceId string = req.FileHash
var uploadBaseRes = UploadBaseRes{}
// 是否强制刷新
var refresh bool
if req.ResourceId != "" {
resourceId = req.ResourceId
}
if req.Refresh == 1 {
refresh = true
}
err := upload.MysqlConn.Transaction(func(tx *gorm.DB) (err error) {
var resourceInfo *gmodel.FsResource
if !refresh {
err = tx.Where("resource_id =?", resourceId).Take(&resourceInfo).Error
if err == nil && resourceInfo.ResourceId != "" {
uploadBaseRes.Status = 1
uploadBaseRes.ResourceId = resourceId
uploadBaseRes.ResourceUrl = *resourceInfo.ResourceUrl
} else {
refresh = true
}
}
if refresh {
contentType := http.DetectContentType(req.FileByte)
// 创建S3对象存储请求
s3req, _ = svc.PutObjectRequest(
&s3.PutObjectInput{
Bucket: bucketName,
Key: &resourceId,
CacheControl: aws.String("no-cache"),
},
)
// 设置请求体为文件数据
s3req.SetBufferBody(req.FileByte)
// 发送请求
err = s3req.Send()
// 检查是否有错误
if err != nil {
logx.Errorf("err:%+vdesc:%+v", err, "fail.upload.s3req")
return err
} else {
var url = s3req.HTTPRequest.URL.String()
// 打印请求URL
// logx.Info(url)
uploadBaseRes.Status = 1
uploadBaseRes.ResourceId = resourceId
uploadBaseRes.ResourceUrl = url
var version string = "0.0.1"
var nowTime = time.Now().UTC()
var dbData = gmodel.FsResource{
ResourceId: resourceId,
UserId: &req.UserId,
GuestId: &req.GuestId,
ResourceType: &contentType,
ResourceUrl: &url,
Version: &version,
UploadedAt: &nowTime,
Metadata: &metadataB,
ApiType: &apiType,
BucketName: bucketName,
Source: &req.Source,
}
if refresh {
err = tx.Save(&dbData).Error
} else {
err = tx.Create(&dbData).Error
}
if err != nil {
logx.Errorf("err:%+vdesc:%+v", err, "fail.upload.resourceInfoAdd.mysql")
return err
}
}
}
return nil
})
if err != nil {
return nil, err
}
return &uploadBaseRes, err
}
// 根据URL上传文件
func (upload *Upload) UploadFileByUrl(fileHash string, url string, uploadBucket int64) error {
// 定义存储桶名称
var bucketName string
// 根据类别选择存储桶
switch uploadBucket {
case 2:
bucketName = *basic.TempfileBucketName
case 3:
bucketName = *basic.StorageBucketName
default:
bucketName = *basic.StorageBucketName
}
switch upload.UploadType {
case "oss":
yunFileTmpPath := fileHash
// 创建OSSClient实例。
clientOss, err := oss.New(upload.AliyunOSS.Endpoint, upload.AliyunOSS.AccessKeyId, upload.AliyunOSS.AccessKeySecret)
if err != nil {
return err
}
bucket, err := clientOss.Bucket(bucketName)
if err != nil {
return err
}
// 创建一个 HTTP 客户端
client := &http.Client{}
// 发送一个 GET 请求
resp, err := client.Get(url)
if err != nil {
return err
}
// 关闭响应
defer resp.Body.Close()
// 读取响应内容
buffer, err := io.ReadAll(resp.Body)
if err != nil {
return err
}
err = bucket.PutObject(yunFileTmpPath, bytes.NewReader(buffer))
if err != nil {
return err
}
return nil
default:
return nil
}
}