217 lines
4.7 KiB
Go
217 lines
4.7 KiB
Go
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 {
|
|
UploadFile(file *multipart.FileHeader) (string, string, error)
|
|
DeleteFile(key string) error
|
|
}
|
|
|
|
// Config 上传配置
|
|
type Config struct {
|
|
Type string // local, aliyun, tencent, qiniu, minio, aws-s3, huawei-obs, cloudflare-r2
|
|
Path string
|
|
MaxSize int64
|
|
}
|
|
|
|
// OSSConfig 完整的OSS配置
|
|
type OSSConfig struct {
|
|
OssType string
|
|
|
|
// Local配置
|
|
LocalPath string
|
|
LocalStorePath string
|
|
|
|
// 七牛云配置
|
|
QiniuZone string
|
|
QiniuBucket string
|
|
QiniuImgPath string
|
|
QiniuAccessKey string
|
|
QiniuSecretKey string
|
|
QiniuUseHTTPS bool
|
|
QiniuUseCdnDomains bool
|
|
|
|
// 腾讯云COS配置
|
|
TencentBucket string
|
|
TencentRegion string
|
|
TencentSecretID string
|
|
TencentSecretKey string
|
|
TencentBaseURL string
|
|
TencentPathPrefix string
|
|
|
|
// 阿里云OSS配置
|
|
AliyunEndpoint string
|
|
AliyunAccessKeyID string
|
|
AliyunAccessKeySecret string
|
|
AliyunBucketName string
|
|
AliyunBucketURL string
|
|
AliyunBasePath string
|
|
|
|
// 华为云OBS配置
|
|
HuaweiPath string
|
|
HuaweiBucket string
|
|
HuaweiEndpoint string
|
|
HuaweiAccessKey string
|
|
HuaweiSecretKey string
|
|
|
|
// AWS S3配置
|
|
AwsBucket string
|
|
AwsRegion string
|
|
AwsEndpoint string
|
|
AwsSecretID string
|
|
AwsSecretKey string
|
|
AwsBaseURL string
|
|
AwsPathPrefix string
|
|
AwsS3ForcePathStyle bool
|
|
AwsDisableSSL bool
|
|
|
|
// Cloudflare R2配置
|
|
CloudflareBucket string
|
|
CloudflareBaseURL string
|
|
CloudflarePath string
|
|
CloudflareAccountID string
|
|
CloudflareAccessKeyID string
|
|
CloudflareSecretAccessKey string
|
|
|
|
// MinIO配置
|
|
MinioEndpoint string
|
|
MinioAccessKeyID string
|
|
MinioAccessKeySecret string
|
|
MinioBucketName string
|
|
MinioUseSSL bool
|
|
MinioBasePath string
|
|
MinioBucketURL string
|
|
}
|
|
|
|
// NewOSS 根据配置创建OSS实例
|
|
func NewOSS(cfg *OSSConfig) (OSS, error) {
|
|
switch cfg.OssType {
|
|
case "local":
|
|
return NewLocal(cfg.LocalStorePath, cfg.LocalPath), nil
|
|
case "qiniu":
|
|
return NewQiniu(
|
|
cfg.QiniuZone,
|
|
cfg.QiniuBucket,
|
|
cfg.QiniuImgPath,
|
|
cfg.QiniuAccessKey,
|
|
cfg.QiniuSecretKey,
|
|
cfg.QiniuUseHTTPS,
|
|
cfg.QiniuUseCdnDomains,
|
|
), nil
|
|
case "tencent-cos":
|
|
return NewTencent(
|
|
cfg.TencentBucket,
|
|
cfg.TencentRegion,
|
|
cfg.TencentSecretID,
|
|
cfg.TencentSecretKey,
|
|
cfg.TencentBaseURL,
|
|
cfg.TencentPathPrefix,
|
|
), nil
|
|
case "aliyun-oss":
|
|
return NewAliyun(
|
|
cfg.AliyunEndpoint,
|
|
cfg.AliyunAccessKeyID,
|
|
cfg.AliyunAccessKeySecret,
|
|
cfg.AliyunBucketName,
|
|
cfg.AliyunBucketURL,
|
|
cfg.AliyunBasePath,
|
|
), nil
|
|
case "huawei-obs":
|
|
return NewHuaweiObs(
|
|
cfg.HuaweiPath,
|
|
cfg.HuaweiBucket,
|
|
cfg.HuaweiEndpoint,
|
|
cfg.HuaweiAccessKey,
|
|
cfg.HuaweiSecretKey,
|
|
), nil
|
|
case "aws-s3":
|
|
return NewAwsS3(
|
|
cfg.AwsBucket,
|
|
cfg.AwsRegion,
|
|
cfg.AwsEndpoint,
|
|
cfg.AwsSecretID,
|
|
cfg.AwsSecretKey,
|
|
cfg.AwsBaseURL,
|
|
cfg.AwsPathPrefix,
|
|
cfg.AwsS3ForcePathStyle,
|
|
cfg.AwsDisableSSL,
|
|
), nil
|
|
case "cloudflare-r2":
|
|
return NewCloudflareR2(
|
|
cfg.CloudflareBucket,
|
|
cfg.CloudflareBaseURL,
|
|
cfg.CloudflarePath,
|
|
cfg.CloudflareAccountID,
|
|
cfg.CloudflareAccessKeyID,
|
|
cfg.CloudflareSecretAccessKey,
|
|
), nil
|
|
case "minio":
|
|
return NewMinio(
|
|
cfg.MinioAccessKeyID,
|
|
cfg.MinioAccessKeySecret,
|
|
cfg.MinioBucketName,
|
|
cfg.MinioEndpoint,
|
|
cfg.MinioBasePath,
|
|
cfg.MinioUseSSL,
|
|
), nil
|
|
default:
|
|
return NewLocal(cfg.LocalStorePath, cfg.LocalPath), nil
|
|
}
|
|
}
|
|
|
|
// 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",
|
|
}
|