package
module
Version:
v0.0.0-...-035b907
Opens a new window with list of versions in this module.
Published: Feb 13, 2026
License: MIT
Opens a new window with license information.
Imports: 7
Opens a new window with list of imports.
Imported by: 0
Opens a new window with list of known importers.
README
¶
📦 پکیج FileStore – ماژول حرفهای ذخیرهسازی فایل با Golang و MinIO
یک ماژول Production-Ready، مستقل از فریمورک و قابل تعویض با هر Storage Provider برای مدیریت فایلها در پروژههای Golang.
این ماژول بر اساس اصول Clean Architecture طراحی شده و امکان تعویض MinIO با هر Storage دیگری (S3, GCS, Azure) را فراهم میکند.
✨ ویژگیها
🏗 معماری حرفهای
- کاملاً مستقل از Gin یا هر فریمورک دیگر
- طراحی مبتنی بر Interface و Abstraction
- قابل جایگزینی با هر storage provider
- بدون وابستگی به HTTP layer
🆔 مدیریت حرفهای شناسهها
- استفاده از UUID برای نام فایل در Storage (جلوگیری از تداخل)
- استفاده از ULID برای شناسه public API (sortable و خواناتر)
📤 قابلیتهای اصلی
- آپلود فایل (Streaming، بدون بارگذاری کامل در حافظه)
- دانلود امن فایل
- حذف فایل
- تولید Presigned URL با زمان انقضا
- لیست فایلها با فیلتر prefix / suffix
- پشتیبانی از Versioning در صورت فعال بودن Bucket
🚀 عملکرد بالا
- استفاده کامل از context.Context
- پشتیبانی از concurrency بالا
- مصرف بهینه حافظه برای فایلهای حجیم
- Retry mechanism
- Structured Logging
- قابل استفاده در محیطهای High Throughput
🔐 امنیت
- پشتیبانی از Server-Side Encryption
- اعتبارسنجی اندازه و نوع فایل
- Presigned URL با مدت اعتبار مشخص
- جداسازی Domain Errors از Infra Errors
🧩 راهاندازی docker
docker compose up -d
🛠️ نصب
go get github.com/Skryldev/filestore
go get github.com/minio/minio-go/v7
go get github.com/google/uuid
go get github.com/oklog/ulid/v2
1️⃣ ساخت Config
cfg, err := filestore.LoadFromEnv()
if err != nil {
log.Fatal(err)
}
یا ساخت دستی:
cfg := &filestore.Config{
Endpoint: "localhost:9000",
AccessKey: "minioadmin",
SecretKey: "minioadmin",
UseSSL: false,
Bucket: "files",
}
🚀 استفاده کامل از ماژول
2️⃣ ساخت Logger
logger := filestore.NewZapLogger()
3️⃣ ساخت Storage
storage, err := minioadapter.New(cfg, logger)
if err != nil {
log.Fatal(err)
}
4️⃣ آپلود فایل
file, err := os.Open("test.jpg")
if err != nil {
log.Fatal(err)
}
defer file.Close()
stat, _ := file.Stat()
info, err := storage.Upload(
context.Background(),
file,
stat.Size(),
"test.jpg",
filestore.UploadOptions{
ContentType: "image/jpeg",
},
)
if err != nil {
log.Fatal(err)
}
fmt.Println("Public ID:", info.ID)
5️⃣ دانلود فایل
reader, meta, err := storage.Download(ctx, publicID)
if err != nil {
log.Fatal(err)
}
defer reader.Close()
io.Copy(os.Stdout, reader)
6️⃣ حذف فایل
err := storage.Delete(ctx, publicID)
if err != nil {
log.Fatal(err)
}
7️⃣ تولید Presigned URL
url, err := storage.PresignedURL(ctx, publicID, 15*time.Minute)
if err != nil {
log.Fatal(err)
}
fmt.Println(url)
8️⃣ لیست فایلها
files, err := storage.List(ctx, filestore.ListOptions{
Prefix: "images/",
})
if err != nil {
log.Fatal(err)
}
for _, f := range files {
fmt.Println(f.ID, f.Name)
}
🔌 اتصال به Gin (اختیاری)
این ماژول مستقل از Gin است، اما میتوانید adaptor بسازید:
func UploadHandler(storage filestore.Storage) gin.HandlerFunc {
return func(c *gin.Context) {
file, header, err := c.Request.FormFile("file")
if err != nil {
c.JSON(400, gin.H{"error": err.Error()})
return
}
defer file.Close()
info, err := storage.Upload(
c.Request.Context(),
file,
header.Size,
header.Filename,
filestore.UploadOptions{
ContentType: header.Header.Get("Content-Type"),
},
)
if err != nil {
c.JSON(500, gin.H{"error": err.Error()})
return
}
c.JSON(201, info)
}
}
⚡ بهترین شیوههای استفاده در Production
- ✔ همیشه از Context با timeout استفاده کنید
- ✔ Bucket versioning را فعال کنید
- ✔ Server-Side Encryption را فعال کنید
- ✔ اندازه فایل را قبل از آپلود validate کنید
- ✔ Logging را با request ID enrich کنید
- ✔ Presigned URL مدت کوتاه داشته باشد
🔄 توسعه در آینده
این ماژول به سادگی قابل گسترش است:
- پیادهسازی S3 Adapter
- اضافه کردن Metadata persistence
- اضافه کردن Event-driven publishing
- اضافه کردن OpenTelemetry tracing
- پیادهسازی Rate limiting در adaptor
📌 جمعبندی
ماژول Filestore:
- 🧱 مستقل از فریمورک
- 🧩 قابل جایگزینی
- 🚀 آماده استفاده در Production
- 🔐 امن
- ⚙️ بهینه و scalable
- 🧠 طراحیشده با اصول Clean Architecture
Documentation
¶
View Source
var (
ErrInvalidFileSize = errors.New("invalid file size")
ErrInvalidFileName = errors.New("invalid file name")
ErrInvalidMimeType = errors.New("invalid mime type")
ErrFileTooLarge = errors.New("file exceeds allowed size")
ErrFileNotFound = errors.New("file not found")
ErrFileAlreadyExists = errors.New("file already exists")
ErrStorageUnavailable = errors.New("storage service unavailable")
ErrUnauthorizedAccess = errors.New("unauthorized file access")
ErrVersionNotFound = errors.New("file version not found")
)
Logger interface همان است
type Storage interface {
Upload(ctx context.Context, reader io.Reader, size int64, originalName string, opts UploadOptions) (*FileInfo, error)
Download(ctx context.Context, id string) (io.ReadCloser, *FileInfo, error)
Delete(ctx context.Context, id string) error
PresignedURL(ctx context.Context, id string, expiry time.Duration) (string, error)
List(ctx context.Context, opts ListOptions) ([]FileInfo, error)
}
type ZapLogger struct {
}
ZapLogger حرفهای با zap
NewZapLogger یک logger حرفهای با JSON output میسازد
Error با context و فیلدهای دلخواه
Info با context و فیلدهای دلخواه
Source Files
¶
Directories
¶
Click to show internal directories.
Click to hide internal directories.