Documentation
¶
Overview ¶
Package gouploader 提供生产级文件上传工具包,适用于 Gin 框架。
功能特性:
- 普通单文件上传(流式传输,内存恒定)
- 分片上传,支持断点续传
- 可插拔存储:本地磁盘、S3 兼容(MinIO/阿里云/腾讯云/华为云/AWS)
- 文件完整性校验(MD5/SHA256)
- 并发安全的分片状态管理
- 可配置限制与回调
快速开始:
uploader, err := gouploader.New(
gouploader.WithLocalStorage("./uploads"),
gouploader.WithMaxFileSize(2 << 30), // 2GB
gouploader.WithOnUploadComplete(func(r *gouploader.UploadResult) {
log.Printf("上传完成: %s -> %s", r.FileName, r.StorageKey)
}),
)
uploader.RegisterRoutes(r.Group("/api/v1/upload"))
Example (Basic) ¶
Example_basic demonstrates the simplest usage with local storage.
package main
import (
"fmt"
"log"
"github.com/gin-gonic/gin"
"github.com/gtkit/gouploader"
)
func main() {
r := gin.Default()
uploader, err := gouploader.New(
gouploader.WithLocalStorage("./uploads"),
)
if err != nil {
log.Fatal(err)
}
uploader.RegisterRoutes(r.Group("/api/v1/upload"))
defer uploader.Close()
// r.Run(":8080")
fmt.Println("routes registered")
}
Output: routes registered
Example (CustomRoutes) ¶
Example_customRoutes demonstrates registering routes individually with custom middleware.
package main
import (
"fmt"
"log"
"github.com/gin-gonic/gin"
"github.com/gtkit/gouploader"
)
func main() {
r := gin.Default()
uploader, err := gouploader.New(
gouploader.WithLocalStorage("./uploads"),
)
if err != nil {
log.Fatal(err)
}
// Register routes individually with custom middleware.
auth := func(c *gin.Context) { c.Next() } // your auth middleware
v1 := r.Group("/api/v1", auth)
{
v1.POST("/upload", uploader.HandleUpload())
v1.POST("/upload/chunk/init", uploader.HandleChunkInit())
v1.POST("/upload/chunk", uploader.HandleChunkUpload())
v1.GET("/upload/chunk/status/:upload_id", uploader.HandleChunkStatus())
v1.POST("/upload/chunk/merge/:upload_id", uploader.HandleChunkMerge())
v1.DELETE("/upload/chunk/:upload_id", uploader.HandleChunkAbort())
}
fmt.Println("custom routes registered")
}
Output: custom routes registered
Example (S3) ¶
Example_s3 demonstrates using S3-compatible storage (MinIO/阿里云/腾讯云/华为云).
package main
import (
"fmt"
"log"
"github.com/gin-gonic/gin"
"github.com/gtkit/gouploader"
)
func main() {
r := gin.Default()
uploader, err := gouploader.New(
gouploader.WithS3Storage(gouploader.S3Config{
// MinIO:
// Endpoint: "127.0.0.1:9000",
// 阿里云 OSS:
// Endpoint: "oss-cn-hangzhou.aliyuncs.com",
// 腾讯云 COS:
// Endpoint: "cos.ap-guangzhou.myqcloud.com",
// 华为云 OBS:
// Endpoint: "obs.cn-north-4.myhuaweicloud.com",
Endpoint: "127.0.0.1:9000",
AccessKey: "minioadmin",
SecretKey: "minioadmin",
Bucket: "uploads",
Region: "us-east-1",
UseSSL: false,
}),
gouploader.WithMaxFileSize(10<<30), // 10GB
gouploader.WithChunkSize(
10<<20, // default: 10MB
1<<20, // min: 1MB
50<<20, // max: 50MB
),
)
if err != nil {
log.Fatal(err)
}
uploader.RegisterRoutes(r.Group("/api/v1/upload"))
fmt.Println("s3 routes registered")
}
Output:
Example (WithCallback) ¶
Example_withCallback demonstrates how to handle post-upload business logic.
package main
import (
"fmt"
"log"
"github.com/gin-gonic/gin"
"github.com/gtkit/gouploader"
)
func main() {
r := gin.Default()
uploader, err := gouploader.New(
gouploader.WithLocalStorage("./uploads"),
gouploader.WithMaxFileSize(2<<30), // 2GB
gouploader.WithAllowedTypes(".jpg", ".png", ".mp4", ".pdf"),
gouploader.WithHashAlgorithm("sha256"),
gouploader.WithOnUploadComplete(func(result *gouploader.UploadResult) {
// This callback fires after every successful upload.
// Use it to save metadata to your database, send notifications, etc.
log.Printf("file uploaded: %s -> %s (checksum: %s)",
result.FileName, result.StorageKey, result.Checksum)
}),
)
if err != nil {
log.Fatal(err)
}
uploader.RegisterRoutes(r.Group("/api/v1/upload"))
defer uploader.Close()
// r.Run(":8080")
fmt.Println("routes registered")
}
Output: routes registered
Index ¶
- Constants
- Variables
- func CORS(cfg CORSConfig) gin.HandlerFunc
- type AWSSTSConfig
- type AliyunSTSConfig
- type CORSConfig
- type ChunkInitRequest
- type ChunkInitResponse
- type ChunkStatusResponse
- type ChunkUploadResponse
- type DirectCompleteRequest
- type DirectTokenRequest
- type DirectTokenResponse
- type DirectUploadResult
- type Error
- type HuaweiSTSConfig
- type Option
- func WithAWSSTS(cfg AWSSTSConfig) Option
- func WithAliyunSTS(cfg AliyunSTSConfig) Option
- func WithAllowedTypes(types ...string) Option
- func WithChunkCleanupInterval(interval time.Duration) Option
- func WithChunkSessionTTL(ttl time.Duration) Option
- func WithChunkSize(defaultSize, minSize, maxSize int64) Option
- func WithChunkTempDir(dir string) Option
- func WithHashAlgorithm(algo string) Option
- func WithHuaweiSTS(cfg HuaweiSTSConfig) Option
- func WithLocalStorage(basePath string) Option
- func WithMaxFileSize(size int64) Option
- func WithOnDirectUploadComplete(fn func(result *DirectUploadResult)) Option
- func WithOnUploadComplete(fn func(result *UploadResult)) Option
- func WithS3Storage(s3 S3Config) Option
- func WithSTSKeyPrefix(fn func(c *gin.Context) string) Option
- func WithSTSProvider(p STSProvider) Option
- func WithStorage(s Storage) Option
- func WithTencentSTS(cfg TencentSTSConfig) Option
- type S3Config
- type STSCredential
- type STSProvider
- type Storage
- type TencentSTSConfig
- type UploadResult
- type Uploader
- func (u *Uploader) Close()
- func (u *Uploader) HandleChunkAbort() gin.HandlerFunc
- func (u *Uploader) HandleChunkInit() gin.HandlerFunc
- func (u *Uploader) HandleChunkMerge() gin.HandlerFunc
- func (u *Uploader) HandleChunkStatus() gin.HandlerFunc
- func (u *Uploader) HandleChunkUpload() gin.HandlerFunc
- func (u *Uploader) HandleDirectCallback() gin.HandlerFunc
- func (u *Uploader) HandleDirectComplete() gin.HandlerFunc
- func (u *Uploader) HandleDirectToken() gin.HandlerFunc
- func (u *Uploader) HandleUpload() gin.HandlerFunc
- func (u *Uploader) RegisterRoutes(group *gin.RouterGroup)
Examples ¶
Constants ¶
const ( CodeFileTooLarge = types.CodeFileTooLarge // 文件超过大小限制 CodeFileTypeNotAllow = types.CodeFileTypeNotAllow // 文件类型不允许 CodeChecksumMismatch = types.CodeChecksumMismatch // 校验和不匹配 CodeFileReadError = types.CodeFileReadError // 文件读取错误 CodeInvalidParam = types.CodeInvalidParam // 参数无效 CodeMultipartError = types.CodeMultipartError // multipart 解析错误 CodeSessionNotFound = types.CodeSessionNotFound // 上传会话不存在 CodeSessionExpired = types.CodeSessionExpired // 上传会话已过期 CodeChunkIndexOutRange = types.CodeChunkIndexOutRange // 分片索引越界 CodeChunkDuplicate = types.CodeChunkDuplicate // 分片重复上传 CodeChunkHashMismatch = types.CodeChunkHashMismatch // 分片校验和不匹配 CodeMergeIncomplete = types.CodeMergeIncomplete // 分片未全部上传 CodeMergeHashFailed = types.CodeMergeHashFailed // 合并后校验失败 CodeStorageWriteFail = types.CodeStorageWriteFail // 存储写入失败 CodeStorageReadFail = types.CodeStorageReadFail // 存储读取失败 CodeStorageDeleteFail = types.CodeStorageDeleteFail // 存储删除失败 CodeSTSNotConfigured = types.CodeSTSNotConfigured // STS 未配置 CodeSTSIssueFailed = types.CodeSTSIssueFailed // STS 凭证签发失败 CodeCallbackVerifyFail = types.CodeCallbackVerifyFail // 回调验签失败 CodeDirectFileNotFound = types.CodeDirectFileNotFound // 直传文件不存在 )
错误码常量。
const Version = "v1.0.0"
Variables ¶
var ( ErrFileTooLarge = types.ErrFileTooLarge ErrFileTypeNotAllow = types.ErrFileTypeNotAllow ErrChecksumMismatch = types.ErrChecksumMismatch ErrInvalidParam = types.ErrInvalidParam ErrMultipartError = types.ErrMultipartError ErrSessionNotFound = types.ErrSessionNotFound ErrSessionExpired = types.ErrSessionExpired ErrChunkIndexOutRange = types.ErrChunkIndexOutRange ErrChunkHashMismatch = types.ErrChunkHashMismatch ErrMergeIncomplete = types.ErrMergeIncomplete ErrMergeHashFailed = types.ErrMergeHashFailed ErrStorageWrite = types.ErrStorageWrite ErrStorageRead = types.ErrStorageRead ErrStorageDelete = types.ErrStorageDelete ErrSTSNotConfigured = types.ErrSTSNotConfigured ErrSTSIssueFailed = types.ErrSTSIssueFailed ErrCallbackVerifyFail = types.ErrCallbackVerifyFail ErrDirectFileNotFound = types.ErrDirectFileNotFound )
预定义错误。
Functions ¶
func CORS ¶
func CORS(cfg CORSConfig) gin.HandlerFunc
CORS 返回处理跨域请求的 Gin 中间件。
用法:
group := r.Group("/api/v1/upload")
group.Use(gouploader.CORS(gouploader.CORSConfig{
AllowOrigins: []string{"https://example.com"},
}))
uploader.RegisterRoutes(group)
Types ¶
type CORSConfig ¶
type CORSConfig struct {
// AllowOrigins 允许访问的源列表。
// 使用 "*" 允许所有源(不建议生产环境使用)。
AllowOrigins []string
// AllowHeaders 客户端可以发送的额外请求头。
// 默认请求头(Content-Type, X-Request-ID)始终包含。
AllowHeaders []string
// ExposeHeaders 客户端可以读取的额外响应头。
ExposeHeaders []string
// AllowCredentials 是否允许携带凭据(Cookie 等)。
AllowCredentials bool
// MaxAge 预检请求结果的缓存时间(秒)。默认 86400(24小时)。
MaxAge int
}
CORSConfig 跨域资源共享配置。
type ChunkInitRequest ¶
type ChunkInitRequest = types.ChunkInitRequest
ChunkInitRequest 初始化分片上传的 JSON 请求体。
type ChunkInitResponse ¶
type ChunkInitResponse = types.ChunkInitResponse
ChunkInitResponse 分片上传会话创建后的响应。
type ChunkStatusResponse ¶
type ChunkStatusResponse = types.ChunkStatusResponse
ChunkStatusResponse 查询分片上传状态的响应。
type ChunkUploadResponse ¶
type ChunkUploadResponse = types.ChunkUploadResponse
ChunkUploadResponse 单个分片上传后的响应。
type DirectCompleteRequest ¶
type DirectCompleteRequest = types.DirectCompleteRequest
DirectCompleteRequest 前端确认上传完成的请求体。
type DirectTokenRequest ¶
type DirectTokenRequest = types.DirectTokenRequest
DirectTokenRequest 请求 STS 凭证的请求体。
type DirectTokenResponse ¶
type DirectTokenResponse = types.DirectTokenResponse
DirectTokenResponse STS 凭证响应。
type DirectUploadResult ¶
type DirectUploadResult = types.DirectUploadResult
DirectUploadResult 前端直传完成后的结果。
type Option ¶
type Option func(*config)
Option 用于配置 Uploader。
func WithAllowedTypes ¶
WithAllowedTypes 设置允许的文件扩展名(如 ".jpg", ".png", ".mp4")。 空列表表示允许所有类型。
func WithChunkCleanupInterval ¶
WithChunkCleanupInterval 设置过期会话的清理间隔。 interval 必须为正数,否则 panic。
func WithChunkSessionTTL ¶
WithChunkSessionTTL 设置分片上传会话的过期时间。
func WithChunkSize ¶
WithChunkSize 设置默认、最小和最大分片大小。
func WithHashAlgorithm ¶
WithHashAlgorithm 设置校验和算法("md5" 或 "sha256")。
func WithOnDirectUploadComplete ¶
func WithOnDirectUploadComplete(fn func(result *DirectUploadResult)) Option
WithOnDirectUploadComplete 注册直传完成后的回调。 在 Complete 或 Callback 确认文件上传成功后触发。
func WithOnUploadComplete ¶
func WithOnUploadComplete(fn func(result *UploadResult)) Option
WithOnUploadComplete 注册上传完成后的回调函数。 每次上传成功后触发(包括普通上传和分片合并)。 可用于保存数据库、发送通知等业务逻辑。
func WithSTSKeyPrefix ¶
WithSTSKeyPrefix 设置生成 keyPrefix 的函数。 默认按日期生成,如 "direct/2026/04/09/"。 可用于按用户 ID 隔离:func(c *gin.Context) string { return "user-" + getUserID(c) + "/" }
func WithSTSProvider ¶
func WithSTSProvider(p STSProvider) Option
WithSTSProvider 设置自定义 STS Provider 实现。
func WithStorage ¶
WithStorage 设置自定义 Storage 实现。 会覆盖 WithLocalStorage 和 WithS3Storage。
func WithTencentSTS ¶
func WithTencentSTS(cfg TencentSTSConfig) Option
WithTencentSTS 配置腾讯云 COS STS 直传。
type S3Config ¶
type S3Config struct {
Endpoint string
AccessKey string
SecretKey string
Bucket string
Region string
UseSSL bool
}
S3Config 包含 S3 兼容对象存储的连接参数。
Endpoint 示例:
MinIO: "127.0.0.1:9000" 阿里云 OSS: "oss-cn-hangzhou.aliyuncs.com" 腾讯云 COS: "cos.ap-guangzhou.myqcloud.com" 华为云 OBS: "obs.cn-north-4.myhuaweicloud.com" AWS S3: "s3.us-east-1.amazonaws.com"
type Storage ¶
Storage 抽象文件持久化层。 所有方法均使用 io.Reader 流式传输,不会将完整文件缓冲到内存。
内置实现:本地磁盘、S3 兼容(MinIO/阿里云/腾讯云/华为云/AWS)。 也可通过 WithStorage 选项提供自定义实现。
type Uploader ¶
type Uploader struct {
// contains filtered or unexported fields
}
Uploader 是 gouploader 包的主入口。
func (*Uploader) Close ¶
func (u *Uploader) Close()
Close 释放 Uploader 持有的资源(停止后台清理协程)。 在 Uploader 不再使用或应用关闭时必须调用。
func (*Uploader) HandleChunkAbort ¶
func (u *Uploader) HandleChunkAbort() gin.HandlerFunc
HandleChunkAbort 返回中止分片上传的 Gin 处理函数。
func (*Uploader) HandleChunkInit ¶
func (u *Uploader) HandleChunkInit() gin.HandlerFunc
HandleChunkInit 返回分片上传初始化的 Gin 处理函数。
func (*Uploader) HandleChunkMerge ¶
func (u *Uploader) HandleChunkMerge() gin.HandlerFunc
HandleChunkMerge 返回合并分片的 Gin 处理函数。
func (*Uploader) HandleChunkStatus ¶
func (u *Uploader) HandleChunkStatus() gin.HandlerFunc
HandleChunkStatus 返回查询分片上传状态的 Gin 处理函数。
func (*Uploader) HandleChunkUpload ¶
func (u *Uploader) HandleChunkUpload() gin.HandlerFunc
HandleChunkUpload 返回分片上传的 Gin 处理函数。
func (*Uploader) HandleDirectCallback ¶
func (u *Uploader) HandleDirectCallback() gin.HandlerFunc
HandleDirectCallback 返回云存储回调的 Gin 处理函数。 如果未配置 STS 直传,返回的处理函数会响应 503 错误。
func (*Uploader) HandleDirectComplete ¶
func (u *Uploader) HandleDirectComplete() gin.HandlerFunc
HandleDirectComplete 返回前端确认上传完成的 Gin 处理函数。 如果未配置 STS 直传,返回的处理函数会响应 503 错误。
func (*Uploader) HandleDirectToken ¶
func (u *Uploader) HandleDirectToken() gin.HandlerFunc
HandleDirectToken 返回签发 STS 凭证的 Gin 处理函数。 如果未配置 STS 直传,返回的处理函数会响应 503 错误。
func (*Uploader) HandleUpload ¶
func (u *Uploader) HandleUpload() gin.HandlerFunc
HandleUpload 返回普通上传的 Gin 处理函数。 用于手动注册路由(搭配自定义中间件)。
func (*Uploader) RegisterRoutes ¶
func (u *Uploader) RegisterRoutes(group *gin.RouterGroup)
RegisterRoutes 在给定的 Gin 路由组上注册所有上传接口。
注册的路由:
POST {group}/ - 普通单文件上传
POST {group}/chunk/init - 初始化分片上传会话
POST {group}/chunk - 上传单个分片
GET {group}/chunk/status/:upload_id - 查询上传进度(断点续传)
POST {group}/chunk/merge/:upload_id - 合并所有分片
DELETE {group}/chunk/:upload_id - 中止并清理分片上传
如果配置了 STS 直传,还会注册:
POST {group}/direct/token - 签发 STS 临时凭证
POST {group}/direct/callback - 云存储上传完成回调
POST {group}/direct/complete - 前端确认上传完成