首次提交:初始化项目代码
This commit is contained in:
@@ -0,0 +1,216 @@
|
||||
package repository
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
|
||||
"cloudnest/internal/domain/file/repository"
|
||||
"cloudnest/internal/infrastructure/storage"
|
||||
"cloudnest/internal/pkg/errors"
|
||||
"github.com/minio/minio-go/v7"
|
||||
)
|
||||
|
||||
// fileRepository is the MinIO implementation of FileRepository.
|
||||
// fileRepository 是 FileRepository 的 MinIO 实现。
|
||||
//
|
||||
// This struct implements the FileRepository interface using MinIO for object storage operations.
|
||||
//
|
||||
// 此结构体使用 MinIO 实现了 FileRepository 接口,用于对象存储操作。
|
||||
type fileRepository struct {
|
||||
minio *storage.MinioClient
|
||||
}
|
||||
|
||||
// NewFileRepository creates a new file repository.
|
||||
// NewFileRepository 创建一个新的文件仓储。
|
||||
//
|
||||
// Parameters:
|
||||
// - minio: The MinIO client for storage operations.
|
||||
//
|
||||
// Returns:
|
||||
// - repository.FileRepository: A FileRepository implementation.
|
||||
//
|
||||
// 参数:
|
||||
// - minio: 用于存储操作的 MinIO 客户端。
|
||||
//
|
||||
// 返回值:
|
||||
// - repository.FileRepository: FileRepository 的实现。
|
||||
func NewFileRepository(minio *storage.MinioClient) repository.FileRepository {
|
||||
return &fileRepository{minio: minio}
|
||||
}
|
||||
|
||||
// Upload uploads a file to the object storage.
|
||||
// Upload 将文件上传到对象存储。
|
||||
//
|
||||
// Parameters:
|
||||
// - bucket: The target bucket name.
|
||||
// - objectName: The unique name/path for the object.
|
||||
// - reader: The file content reader.
|
||||
// - size: The size of the file in bytes.
|
||||
// - contentType: The MIME type of the file.
|
||||
//
|
||||
// Returns:
|
||||
// - error: An error if the operation fails.
|
||||
//
|
||||
// 参数:
|
||||
// - bucket: 目标桶名称。
|
||||
// - objectName: 对象的唯一名称/路径。
|
||||
// - reader: 文件内容读取器。
|
||||
// - size: 文件大小(字节)。
|
||||
// - contentType: 文件的 MIME 类型。
|
||||
//
|
||||
// 返回值:
|
||||
// - error: 如果操作失败则返回错误。
|
||||
func (r *fileRepository) Upload(bucket, objectName string, reader io.Reader, size int64, contentType string) error {
|
||||
_, err := r.minio.Client.PutObject(context.Background(), bucket, objectName, reader, size, minio.PutObjectOptions{ContentType: contentType})
|
||||
if err != nil {
|
||||
return errors.InternalError("上传文件失败", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// List retrieves a list of files under the specified prefix with metadata.
|
||||
// List 获取指定前缀下的文件列表及其元数据。
|
||||
//
|
||||
// Parameters:
|
||||
// - bucket: The bucket name.
|
||||
// - prefix: The prefix/path to filter files.
|
||||
//
|
||||
// Returns:
|
||||
// - []repository.FileInfo: A list of file information.
|
||||
// - error: An error if the operation fails.
|
||||
//
|
||||
// 参数:
|
||||
// - bucket: 桶名称。
|
||||
// - prefix: 用于过滤文件的前缀/路径。
|
||||
//
|
||||
// 返回值:
|
||||
// - []repository.FileInfo: 文件信息列表。
|
||||
// - error: 如果操作失败则返回错误。
|
||||
func (r *fileRepository) List(bucket, prefix string) ([]repository.FileInfo, error) {
|
||||
var files []repository.FileInfo
|
||||
for obj := range r.minio.Client.ListObjects(context.Background(), bucket, minio.ListObjectsOptions{Prefix: prefix}) {
|
||||
if obj.Err != nil {
|
||||
return nil, errors.InternalError("获取文件列表失败", obj.Err)
|
||||
}
|
||||
files = append(files, repository.FileInfo{
|
||||
Key: obj.Key,
|
||||
Size: obj.Size,
|
||||
LastModified: obj.LastModified.Format("2006-01-02 15:04:05"),
|
||||
})
|
||||
}
|
||||
return files, nil
|
||||
}
|
||||
|
||||
// PresignDownload generates a pre-signed URL for downloading a file.
|
||||
// PresignDownload 生成用于下载文件的预签名 URL。
|
||||
//
|
||||
// Parameters:
|
||||
// - bucket: The bucket name.
|
||||
// - objectName: The name/path of the object.
|
||||
//
|
||||
// Returns:
|
||||
// - string: The pre-signed download URL.
|
||||
// - error: An error if the operation fails.
|
||||
//
|
||||
// Note:
|
||||
// - The URL expires after storage.PresignDuration (default 24 hours).
|
||||
// - Returns errors.NotFoundError if the file doesn't exist.
|
||||
//
|
||||
// 参数:
|
||||
// - bucket: 桶名称。
|
||||
// - objectName: 对象的名称/路径。
|
||||
//
|
||||
// 返回值:
|
||||
// - string: 预签名下载 URL。
|
||||
// - error: 如果操作失败则返回错误。
|
||||
//
|
||||
// 注意:
|
||||
// - URL 在 storage.PresignDuration(默认 24 小时)后过期。
|
||||
// - 如果文件不存在,返回 errors.NotFoundError。
|
||||
func (r *fileRepository) PresignDownload(bucket, objectName string) (string, error) {
|
||||
url, err := r.minio.Client.PresignedGetObject(context.Background(), bucket, objectName, storage.PresignDuration, nil)
|
||||
if err != nil {
|
||||
return "", errors.NotFound("文件不存在")
|
||||
}
|
||||
return url.String(), nil
|
||||
}
|
||||
|
||||
// Delete removes a file from the object storage.
|
||||
// Delete 从对象存储中删除文件。
|
||||
//
|
||||
// Parameters:
|
||||
// - bucket: The bucket name.
|
||||
// - objectName: The name/path of the object to delete.
|
||||
//
|
||||
// Returns:
|
||||
// - error: An error if the operation fails.
|
||||
//
|
||||
// 参数:
|
||||
// - bucket: 桶名称。
|
||||
// - objectName: 要删除的对象的名称/路径。
|
||||
//
|
||||
// 返回值:
|
||||
// - error: 如果操作失败则返回错误。
|
||||
func (r *fileRepository) Delete(bucket, objectName string) error {
|
||||
err := r.minio.Client.RemoveObject(context.Background(), bucket, objectName, minio.RemoveObjectOptions{})
|
||||
if err != nil {
|
||||
return errors.InternalError("删除文件失败", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetObject retrieves a file as a readable stream from the object storage.
|
||||
// GetObject 从对象存储中获取文件的可读流。
|
||||
//
|
||||
// Parameters:
|
||||
// - bucket: The bucket name.
|
||||
// - objectName: The name/path of the object.
|
||||
//
|
||||
// Returns:
|
||||
// - io.ReadCloser: A readable stream of the file content. Caller must close it.
|
||||
// - int64: The file size in bytes.
|
||||
// - string: The Content-Type of the file.
|
||||
// - error: An error if the operation fails.
|
||||
//
|
||||
// 参数:
|
||||
// - bucket: 桶名称。
|
||||
// - objectName: 对象的名称/路径。
|
||||
//
|
||||
// 返回值:
|
||||
// - io.ReadCloser: 文件内容的可读流。调用方必须关闭它。
|
||||
// - int64: 文件大小(字节)。
|
||||
// - string: 文件的 Content-Type。
|
||||
// - error: 如果操作失败则返回错误。
|
||||
func (r *fileRepository) GetObject(bucket, objectName string) (io.ReadCloser, int64, string, error) {
|
||||
obj, err := r.minio.Client.GetObject(context.Background(), bucket, objectName, minio.GetObjectOptions{})
|
||||
if err != nil {
|
||||
return nil, 0, "", errors.NotFound("文件不存在")
|
||||
}
|
||||
|
||||
info, err := obj.Stat()
|
||||
if err != nil {
|
||||
obj.Close()
|
||||
return nil, 0, "", errors.NotFound("文件不存在")
|
||||
}
|
||||
|
||||
contentType := info.ContentType
|
||||
if contentType == "" {
|
||||
contentType = "application/octet-stream"
|
||||
}
|
||||
|
||||
return obj, info.Size, contentType, nil
|
||||
}
|
||||
|
||||
func (r *fileRepository) GetObjectInfo(bucket, objectName string) (int64, string, error) {
|
||||
info, err := r.minio.Client.StatObject(context.Background(), bucket, objectName, minio.StatObjectOptions{})
|
||||
if err != nil {
|
||||
return 0, "", errors.NotFound("文件不存在")
|
||||
}
|
||||
|
||||
contentType := info.ContentType
|
||||
if contentType == "" {
|
||||
contentType = "application/octet-stream"
|
||||
}
|
||||
|
||||
return info.Size, contentType, nil
|
||||
}
|
||||
Reference in New Issue
Block a user