任务一完成
This commit is contained in:
@@ -0,0 +1,79 @@
|
||||
package upload
|
||||
|
||||
import (
|
||||
"mime/multipart"
|
||||
"path"
|
||||
|
||||
"github.com/aliyun/aliyun-oss-go-sdk/oss"
|
||||
)
|
||||
|
||||
// Aliyun 阿里云OSS
|
||||
type Aliyun struct {
|
||||
Endpoint string
|
||||
AccessKeyID string
|
||||
AccessKeySecret string
|
||||
BucketName string
|
||||
BucketURL string
|
||||
BasePath string
|
||||
}
|
||||
|
||||
// NewAliyun 创建阿里云OSS
|
||||
func NewAliyun(endpoint, accessKeyID, accessKeySecret, bucketName, bucketURL, basePath string) *Aliyun {
|
||||
return &Aliyun{
|
||||
Endpoint: endpoint,
|
||||
AccessKeyID: accessKeyID,
|
||||
AccessKeySecret: accessKeySecret,
|
||||
BucketName: bucketName,
|
||||
BucketURL: bucketURL,
|
||||
BasePath: basePath,
|
||||
}
|
||||
}
|
||||
|
||||
// Upload 上传文件
|
||||
func (a *Aliyun) Upload(file *multipart.FileHeader) (string, string, error) {
|
||||
client, err := oss.New(a.Endpoint, a.AccessKeyID, a.AccessKeySecret)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
|
||||
bucket, err := client.Bucket(a.BucketName)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
|
||||
// 生成文件名和路径
|
||||
fileName := GenerateFileName(file.Filename)
|
||||
filePath := GeneratePath(a.BasePath)
|
||||
key := path.Join(filePath, fileName)
|
||||
|
||||
// 打开文件
|
||||
src, err := file.Open()
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
defer src.Close()
|
||||
|
||||
// 上传
|
||||
if err = bucket.PutObject(key, src); err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
|
||||
// 返回访问URL和key
|
||||
accessURL := a.BucketURL + "/" + key
|
||||
return accessURL, key, nil
|
||||
}
|
||||
|
||||
// Delete 删除文件
|
||||
func (a *Aliyun) Delete(key string) error {
|
||||
client, err := oss.New(a.Endpoint, a.AccessKeyID, a.AccessKeySecret)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
bucket, err := client.Bucket(a.BucketName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return bucket.DeleteObject(key)
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
package upload
|
||||
|
||||
import (
|
||||
"context"
|
||||
"mime/multipart"
|
||||
"path"
|
||||
|
||||
"github.com/aws/aws-sdk-go-v2/aws"
|
||||
"github.com/aws/aws-sdk-go-v2/config"
|
||||
"github.com/aws/aws-sdk-go-v2/credentials"
|
||||
"github.com/aws/aws-sdk-go-v2/service/s3"
|
||||
)
|
||||
|
||||
// AwsS3 AWS S3存储
|
||||
type AwsS3 struct {
|
||||
Bucket string
|
||||
Region string
|
||||
Endpoint string
|
||||
SecretID string
|
||||
SecretKey string
|
||||
BaseURL string
|
||||
PathPrefix string
|
||||
S3ForcePathStyle bool
|
||||
DisableSSL bool
|
||||
}
|
||||
|
||||
// NewAwsS3 创建AWS S3
|
||||
func NewAwsS3(bucket, region, endpoint, secretID, secretKey, baseURL, pathPrefix string, s3ForcePathStyle, disableSSL bool) *AwsS3 {
|
||||
return &AwsS3{
|
||||
Bucket: bucket,
|
||||
Region: region,
|
||||
Endpoint: endpoint,
|
||||
SecretID: secretID,
|
||||
SecretKey: secretKey,
|
||||
BaseURL: baseURL,
|
||||
PathPrefix: pathPrefix,
|
||||
S3ForcePathStyle: s3ForcePathStyle,
|
||||
DisableSSL: disableSSL,
|
||||
}
|
||||
}
|
||||
|
||||
func (a *AwsS3) getClient(ctx context.Context) (*s3.Client, error) {
|
||||
cfg, err := config.LoadDefaultConfig(ctx,
|
||||
config.WithRegion(a.Region),
|
||||
config.WithCredentialsProvider(credentials.NewStaticCredentialsProvider(a.SecretID, a.SecretKey, "")),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
client := s3.NewFromConfig(cfg, func(o *s3.Options) {
|
||||
if a.Endpoint != "" {
|
||||
o.BaseEndpoint = aws.String(a.Endpoint)
|
||||
}
|
||||
o.UsePathStyle = a.S3ForcePathStyle
|
||||
})
|
||||
return client, nil
|
||||
}
|
||||
|
||||
// Upload 上传文件
|
||||
func (a *AwsS3) Upload(file *multipart.FileHeader) (string, string, error) {
|
||||
ctx := context.Background()
|
||||
client, err := a.getClient(ctx)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
|
||||
// 生成文件名和路径
|
||||
fileName := GenerateFileName(file.Filename)
|
||||
filePath := GeneratePath(a.PathPrefix)
|
||||
key := path.Join(filePath, fileName)
|
||||
|
||||
// 打开文件
|
||||
src, err := file.Open()
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
defer src.Close()
|
||||
|
||||
// 上传
|
||||
contentType := file.Header.Get("Content-Type")
|
||||
_, err = client.PutObject(ctx, &s3.PutObjectInput{
|
||||
Bucket: aws.String(a.Bucket),
|
||||
Key: aws.String(key),
|
||||
Body: src,
|
||||
ContentType: aws.String(contentType),
|
||||
})
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
|
||||
// 返回访问URL和key
|
||||
accessURL := a.BaseURL + "/" + key
|
||||
return accessURL, key, nil
|
||||
}
|
||||
|
||||
// Delete 删除文件
|
||||
func (a *AwsS3) Delete(key string) error {
|
||||
ctx := context.Background()
|
||||
client, err := a.getClient(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = client.DeleteObject(ctx, &s3.DeleteObjectInput{
|
||||
Bucket: aws.String(a.Bucket),
|
||||
Key: aws.String(key),
|
||||
})
|
||||
return err
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
package upload
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"mime/multipart"
|
||||
"path"
|
||||
|
||||
"github.com/aws/aws-sdk-go-v2/aws"
|
||||
"github.com/aws/aws-sdk-go-v2/config"
|
||||
"github.com/aws/aws-sdk-go-v2/credentials"
|
||||
"github.com/aws/aws-sdk-go-v2/service/s3"
|
||||
)
|
||||
|
||||
// CloudflareR2 Cloudflare R2存储
|
||||
type CloudflareR2 struct {
|
||||
Bucket string
|
||||
BaseURL string
|
||||
Path string
|
||||
AccountID string
|
||||
AccessKeyID string
|
||||
SecretAccessKey string
|
||||
}
|
||||
|
||||
// NewCloudflareR2 创建Cloudflare R2
|
||||
func NewCloudflareR2(bucket, baseURL, r2Path, accountID, accessKeyID, secretAccessKey string) *CloudflareR2 {
|
||||
return &CloudflareR2{
|
||||
Bucket: bucket,
|
||||
BaseURL: baseURL,
|
||||
Path: r2Path,
|
||||
AccountID: accountID,
|
||||
AccessKeyID: accessKeyID,
|
||||
SecretAccessKey: secretAccessKey,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *CloudflareR2) getClient(ctx context.Context) (*s3.Client, error) {
|
||||
endpoint := fmt.Sprintf("https://%s.r2.cloudflarestorage.com", c.AccountID)
|
||||
|
||||
cfg, err := config.LoadDefaultConfig(ctx,
|
||||
config.WithCredentialsProvider(credentials.NewStaticCredentialsProvider(c.AccessKeyID, c.SecretAccessKey, "")),
|
||||
config.WithRegion("auto"),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
client := s3.NewFromConfig(cfg, func(o *s3.Options) {
|
||||
o.BaseEndpoint = aws.String(endpoint)
|
||||
})
|
||||
return client, nil
|
||||
}
|
||||
|
||||
// Upload 上传文件
|
||||
func (c *CloudflareR2) Upload(file *multipart.FileHeader) (string, string, error) {
|
||||
ctx := context.Background()
|
||||
client, err := c.getClient(ctx)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
|
||||
// 生成文件名和路径
|
||||
fileName := GenerateFileName(file.Filename)
|
||||
filePath := GeneratePath(c.Path)
|
||||
key := path.Join(filePath, fileName)
|
||||
|
||||
// 打开文件
|
||||
src, err := file.Open()
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
defer src.Close()
|
||||
|
||||
// 上传
|
||||
contentType := file.Header.Get("Content-Type")
|
||||
_, err = client.PutObject(ctx, &s3.PutObjectInput{
|
||||
Bucket: aws.String(c.Bucket),
|
||||
Key: aws.String(key),
|
||||
Body: src,
|
||||
ContentType: aws.String(contentType),
|
||||
})
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
|
||||
// 返回访问URL和key
|
||||
accessURL := c.BaseURL + "/" + key
|
||||
return accessURL, key, nil
|
||||
}
|
||||
|
||||
// Delete 删除文件
|
||||
func (c *CloudflareR2) Delete(key string) error {
|
||||
ctx := context.Background()
|
||||
client, err := c.getClient(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = client.DeleteObject(ctx, &s3.DeleteObjectInput{
|
||||
Bucket: aws.String(c.Bucket),
|
||||
Key: aws.String(key),
|
||||
})
|
||||
return err
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
package upload
|
||||
|
||||
import (
|
||||
"mime/multipart"
|
||||
"path"
|
||||
|
||||
"github.com/huaweicloud/huaweicloud-sdk-go-obs/obs"
|
||||
)
|
||||
|
||||
// HuaweiObs 华为云OBS
|
||||
type HuaweiObs struct {
|
||||
Path string
|
||||
Bucket string
|
||||
Endpoint string
|
||||
AccessKey string
|
||||
SecretKey string
|
||||
}
|
||||
|
||||
// NewHuaweiObs 创建华为云OBS
|
||||
func NewHuaweiObs(obsPath, bucket, endpoint, accessKey, secretKey string) *HuaweiObs {
|
||||
return &HuaweiObs{
|
||||
Path: obsPath,
|
||||
Bucket: bucket,
|
||||
Endpoint: endpoint,
|
||||
AccessKey: accessKey,
|
||||
SecretKey: secretKey,
|
||||
}
|
||||
}
|
||||
|
||||
func (h *HuaweiObs) getClient() (*obs.ObsClient, error) {
|
||||
return obs.New(h.AccessKey, h.SecretKey, h.Endpoint)
|
||||
}
|
||||
|
||||
// Upload 上传文件
|
||||
func (h *HuaweiObs) Upload(file *multipart.FileHeader) (string, string, error) {
|
||||
client, err := h.getClient()
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
defer client.Close()
|
||||
|
||||
// 生成文件名和路径
|
||||
fileName := GenerateFileName(file.Filename)
|
||||
filePath := GeneratePath(h.Path)
|
||||
key := path.Join(filePath, fileName)
|
||||
|
||||
// 打开文件
|
||||
src, err := file.Open()
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
defer src.Close()
|
||||
|
||||
// 上传
|
||||
input := &obs.PutObjectInput{}
|
||||
input.Bucket = h.Bucket
|
||||
input.Key = key
|
||||
input.Body = src
|
||||
_, err = client.PutObject(input)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
|
||||
// 返回访问URL和key
|
||||
accessURL := "https://" + h.Bucket + "." + h.Endpoint + "/" + key
|
||||
return accessURL, key, nil
|
||||
}
|
||||
|
||||
// Delete 删除文件
|
||||
func (h *HuaweiObs) Delete(key string) error {
|
||||
client, err := h.getClient()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer client.Close()
|
||||
|
||||
input := &obs.DeleteObjectInput{}
|
||||
input.Bucket = h.Bucket
|
||||
input.Key = key
|
||||
_, err = client.DeleteObject(input)
|
||||
return err
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
package upload
|
||||
|
||||
import (
|
||||
"io"
|
||||
"mime/multipart"
|
||||
"os"
|
||||
"path"
|
||||
)
|
||||
|
||||
// Local 本地存储
|
||||
type Local struct {
|
||||
StorePath string
|
||||
BasePath string
|
||||
}
|
||||
|
||||
// NewLocal 创建本地存储
|
||||
func NewLocal(storePath, basePath string) *Local {
|
||||
return &Local{
|
||||
StorePath: storePath,
|
||||
BasePath: basePath,
|
||||
}
|
||||
}
|
||||
|
||||
// Upload 上传文件
|
||||
func (l *Local) Upload(file *multipart.FileHeader) (string, string, error) {
|
||||
// 生成文件名和路径
|
||||
fileName := GenerateFileName(file.Filename)
|
||||
filePath := GeneratePath(l.BasePath)
|
||||
fullPath := path.Join(l.StorePath, filePath)
|
||||
|
||||
// 创建目录
|
||||
if err := os.MkdirAll(fullPath, os.ModePerm); err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
|
||||
// 打开源文件
|
||||
src, err := file.Open()
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
defer src.Close()
|
||||
|
||||
// 创建目标文件
|
||||
dstPath := path.Join(fullPath, fileName)
|
||||
dst, err := os.Create(dstPath)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
defer dst.Close()
|
||||
|
||||
// 复制文件
|
||||
if _, err = io.Copy(dst, src); err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
|
||||
// 返回访问路径和存储key
|
||||
accessPath := path.Join("/", filePath, fileName)
|
||||
key := path.Join(filePath, fileName)
|
||||
return accessPath, key, nil
|
||||
}
|
||||
|
||||
// Delete 删除文件
|
||||
func (l *Local) Delete(key string) error {
|
||||
fullPath := path.Join(l.StorePath, key)
|
||||
return os.Remove(fullPath)
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
package upload
|
||||
|
||||
import (
|
||||
"context"
|
||||
"mime/multipart"
|
||||
"path"
|
||||
|
||||
"github.com/minio/minio-go/v7"
|
||||
"github.com/minio/minio-go/v7/pkg/credentials"
|
||||
)
|
||||
|
||||
// Minio MinIO存储
|
||||
type Minio struct {
|
||||
ID string
|
||||
Secret string
|
||||
Bucket string
|
||||
Endpoint string
|
||||
BasePath string
|
||||
UseSSL bool
|
||||
}
|
||||
|
||||
// NewMinio 创建MinIO
|
||||
func NewMinio(id, secret, bucket, endpoint, basePath string, useSSL bool) *Minio {
|
||||
return &Minio{
|
||||
ID: id,
|
||||
Secret: secret,
|
||||
Bucket: bucket,
|
||||
Endpoint: endpoint,
|
||||
BasePath: basePath,
|
||||
UseSSL: useSSL,
|
||||
}
|
||||
}
|
||||
|
||||
func (m *Minio) getClient() (*minio.Client, error) {
|
||||
return minio.New(m.Endpoint, &minio.Options{
|
||||
Creds: credentials.NewStaticV4(m.ID, m.Secret, ""),
|
||||
Secure: m.UseSSL,
|
||||
})
|
||||
}
|
||||
|
||||
// Upload 上传文件
|
||||
func (m *Minio) Upload(file *multipart.FileHeader) (string, string, error) {
|
||||
client, err := m.getClient()
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
|
||||
// 生成文件名和路径
|
||||
fileName := GenerateFileName(file.Filename)
|
||||
filePath := GeneratePath(m.BasePath)
|
||||
key := path.Join(filePath, fileName)
|
||||
|
||||
// 打开文件
|
||||
src, err := file.Open()
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
defer src.Close()
|
||||
|
||||
// 上传
|
||||
_, err = client.PutObject(context.Background(), m.Bucket, key, src, file.Size, minio.PutObjectOptions{
|
||||
ContentType: file.Header.Get("Content-Type"),
|
||||
})
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
|
||||
// 返回访问URL和key
|
||||
protocol := "http"
|
||||
if m.UseSSL {
|
||||
protocol = "https"
|
||||
}
|
||||
accessURL := protocol + "://" + m.Endpoint + "/" + m.Bucket + "/" + key
|
||||
return accessURL, key, nil
|
||||
}
|
||||
|
||||
// Delete 删除文件
|
||||
func (m *Minio) Delete(key string) error {
|
||||
client, err := m.getClient()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return client.RemoveObject(context.Background(), m.Bucket, key, minio.RemoveObjectOptions{})
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
package upload
|
||||
|
||||
import (
|
||||
"context"
|
||||
"mime/multipart"
|
||||
"path"
|
||||
|
||||
"github.com/qiniu/go-sdk/v7/auth/qbox"
|
||||
"github.com/qiniu/go-sdk/v7/storage"
|
||||
)
|
||||
|
||||
// Qiniu 七牛云
|
||||
type Qiniu struct {
|
||||
Zone string
|
||||
Bucket string
|
||||
ImgPath string
|
||||
AccessKey string
|
||||
SecretKey string
|
||||
UseHTTPS bool
|
||||
UseCdnDomains bool
|
||||
}
|
||||
|
||||
// NewQiniu 创建七牛云
|
||||
func NewQiniu(zone, bucket, imgPath, accessKey, secretKey string, useHTTPS, useCdnDomains bool) *Qiniu {
|
||||
return &Qiniu{
|
||||
Zone: zone,
|
||||
Bucket: bucket,
|
||||
ImgPath: imgPath,
|
||||
AccessKey: accessKey,
|
||||
SecretKey: secretKey,
|
||||
UseHTTPS: useHTTPS,
|
||||
UseCdnDomains: useCdnDomains,
|
||||
}
|
||||
}
|
||||
|
||||
func (q *Qiniu) getZone() *storage.Region {
|
||||
switch q.Zone {
|
||||
case "ZoneHuadong":
|
||||
return &storage.ZoneHuadong
|
||||
case "ZoneHuabei":
|
||||
return &storage.ZoneHuabei
|
||||
case "ZoneHuanan":
|
||||
return &storage.ZoneHuanan
|
||||
case "ZoneBeimei":
|
||||
return &storage.ZoneBeimei
|
||||
case "ZoneXinjiapo":
|
||||
return &storage.ZoneXinjiapo
|
||||
default:
|
||||
return &storage.ZoneHuadong
|
||||
}
|
||||
}
|
||||
|
||||
// Upload 上传文件
|
||||
func (q *Qiniu) Upload(file *multipart.FileHeader) (string, string, error) {
|
||||
mac := qbox.NewMac(q.AccessKey, q.SecretKey)
|
||||
putPolicy := storage.PutPolicy{Scope: q.Bucket}
|
||||
upToken := putPolicy.UploadToken(mac)
|
||||
|
||||
cfg := storage.Config{
|
||||
Zone: q.getZone(),
|
||||
UseHTTPS: q.UseHTTPS,
|
||||
UseCdnDomains: q.UseCdnDomains,
|
||||
}
|
||||
formUploader := storage.NewFormUploader(&cfg)
|
||||
|
||||
// 生成文件名和路径
|
||||
fileName := GenerateFileName(file.Filename)
|
||||
filePath := GeneratePath("")
|
||||
key := path.Join(filePath, fileName)
|
||||
|
||||
// 打开文件
|
||||
src, err := file.Open()
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
defer src.Close()
|
||||
|
||||
// 上传
|
||||
ret := storage.PutRet{}
|
||||
err = formUploader.Put(context.Background(), &ret, upToken, key, src, file.Size, nil)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
|
||||
// 返回访问URL和key
|
||||
accessURL := q.ImgPath + "/" + key
|
||||
return accessURL, key, nil
|
||||
}
|
||||
|
||||
// Delete 删除文件
|
||||
func (q *Qiniu) Delete(key string) error {
|
||||
mac := qbox.NewMac(q.AccessKey, q.SecretKey)
|
||||
cfg := storage.Config{Zone: q.getZone()}
|
||||
bucketManager := storage.NewBucketManager(mac, &cfg)
|
||||
return bucketManager.Delete(q.Bucket, key)
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
package upload
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"mime/multipart"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"path"
|
||||
|
||||
"github.com/tencentyun/cos-go-sdk-v5"
|
||||
)
|
||||
|
||||
// Tencent 腾讯云COS
|
||||
type Tencent struct {
|
||||
Bucket string
|
||||
Region string
|
||||
SecretID string
|
||||
SecretKey string
|
||||
BaseURL string
|
||||
PathPrefix string
|
||||
}
|
||||
|
||||
// NewTencent 创建腾讯云COS
|
||||
func NewTencent(bucket, region, secretID, secretKey, baseURL, pathPrefix string) *Tencent {
|
||||
return &Tencent{
|
||||
Bucket: bucket,
|
||||
Region: region,
|
||||
SecretID: secretID,
|
||||
SecretKey: secretKey,
|
||||
BaseURL: baseURL,
|
||||
PathPrefix: pathPrefix,
|
||||
}
|
||||
}
|
||||
|
||||
func (t *Tencent) getClient() *cos.Client {
|
||||
u, _ := url.Parse(fmt.Sprintf("https://%s.cos.%s.myqcloud.com", t.Bucket, t.Region))
|
||||
b := &cos.BaseURL{BucketURL: u}
|
||||
return cos.NewClient(b, &http.Client{
|
||||
Transport: &cos.AuthorizationTransport{
|
||||
SecretID: t.SecretID,
|
||||
SecretKey: t.SecretKey,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// Upload 上传文件
|
||||
func (t *Tencent) Upload(file *multipart.FileHeader) (string, string, error) {
|
||||
client := t.getClient()
|
||||
|
||||
// 生成文件名和路径
|
||||
fileName := GenerateFileName(file.Filename)
|
||||
filePath := GeneratePath(t.PathPrefix)
|
||||
key := path.Join(filePath, fileName)
|
||||
|
||||
// 打开文件
|
||||
src, err := file.Open()
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
defer src.Close()
|
||||
|
||||
// 上传
|
||||
_, err = client.Object.Put(context.Background(), key, src, nil)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
|
||||
// 返回访问URL和key
|
||||
accessURL := t.BaseURL + "/" + key
|
||||
return accessURL, key, nil
|
||||
}
|
||||
|
||||
// Delete 删除文件
|
||||
func (t *Tencent) Delete(key string) error {
|
||||
client := t.getClient()
|
||||
_, err := client.Object.Delete(context.Background(), key)
|
||||
return err
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
package upload
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"mime/multipart"
|
||||
"path"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrFileEmpty = errors.New("文件为空")
|
||||
ErrFileTooLarge = errors.New("文件过大")
|
||||
ErrFileTypeError = errors.New("文件类型不允许")
|
||||
)
|
||||
|
||||
// OSS 对象存储接口
|
||||
type OSS interface {
|
||||
Upload(file *multipart.FileHeader) (string, string, error)
|
||||
Delete(key string) error
|
||||
}
|
||||
|
||||
// Config 上传配置
|
||||
type Config struct {
|
||||
Type string // local, aliyun, tencent, qiniu, minio, aws-s3, huawei-obs, cloudflare-r2
|
||||
Path string
|
||||
MaxSize int64
|
||||
}
|
||||
|
||||
// GenerateFileName 生成文件名
|
||||
func GenerateFileName(originalName string) string {
|
||||
ext := path.Ext(originalName)
|
||||
name := uuid.New().String()
|
||||
return name + ext
|
||||
}
|
||||
|
||||
// GeneratePath 生成存储路径
|
||||
func GeneratePath(basePath string) string {
|
||||
now := time.Now()
|
||||
return path.Join(basePath, now.Format("2006/01/02"))
|
||||
}
|
||||
|
||||
// CheckFileSize 检查文件大小
|
||||
func CheckFileSize(size int64, maxSize int64) error {
|
||||
if size > maxSize {
|
||||
return ErrFileTooLarge
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// CheckFileType 检查文件类型
|
||||
func CheckFileType(filename string, allowTypes []string) error {
|
||||
ext := strings.ToLower(path.Ext(filename))
|
||||
for _, t := range allowTypes {
|
||||
if ext == t || t == "*" {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return ErrFileTypeError
|
||||
}
|
||||
|
||||
// DefaultAllowTypes 默认允许的文件类型
|
||||
var DefaultAllowTypes = []string{
|
||||
".jpg", ".jpeg", ".png", ".gif", ".bmp", ".webp",
|
||||
".pdf", ".doc", ".docx", ".xls", ".xlsx", ".ppt", ".pptx",
|
||||
".txt", ".md", ".json", ".xml", ".csv",
|
||||
".zip", ".rar", ".7z", ".tar", ".gz",
|
||||
".mp3", ".mp4", ".avi", ".mov", ".wmv",
|
||||
}
|
||||
Reference in New Issue
Block a user