JCS-pub/common/pkgs/cmd/download_package.go

111 lines
3.2 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package cmd
import (
"fmt"
"io"
"os"
"path/filepath"
cdssdk "gitlink.org.cn/cloudream/common/sdks/storage"
"gitlink.org.cn/cloudream/common/pkgs/distlock"
stgglb "gitlink.org.cn/cloudream/storage/common/globals"
"gitlink.org.cn/cloudream/storage/common/pkgs/iterator"
coormq "gitlink.org.cn/cloudream/storage/common/pkgs/mq/coordinator"
)
// 下载包结构体存储用户ID、包ID和输出路径。
type DownloadPackage struct {
userID cdssdk.UserID
packageID cdssdk.PackageID
outputPath string
}
// 下载包执行上下文,包含分布式锁服务。
type DownloadPackageContext struct {
Distlock *distlock.Service
}
// 新建一个下载包实例。
// userID: 用户标识。
// packageID: 包标识。
// outputPath: 输出路径。
func NewDownloadPackage(userID cdssdk.UserID, packageID cdssdk.PackageID, outputPath string) *DownloadPackage {
return &DownloadPackage{
userID: userID,
packageID: packageID,
outputPath: outputPath,
}
}
// 执行下载包操作。
// ctx: 下载包执行上下文。
// 返回值: 执行过程中可能出现的错误。
func (t *DownloadPackage) Execute(ctx *DownloadPackageContext) error {
// 获取协调器MQ客户端
coorCli, err := stgglb.CoordinatorMQPool.Acquire()
if err != nil {
return fmt.Errorf("new coordinator client: %w", err)
}
defer stgglb.CoordinatorMQPool.Release(coorCli) // 确保释放客户端资源
// 获取包内对象详情
getObjectDetails, err := coorCli.GetPackageObjectDetails(coormq.NewGetPackageObjectDetails(t.packageID))
if err != nil {
return fmt.Errorf("getting package object details: %w", err)
}
// 创建下载对象迭代器
objIter := iterator.NewDownloadObjectIterator(getObjectDetails.Objects, &iterator.DownloadContext{
Distlock: ctx.Distlock,
})
defer objIter.Close() // 确保迭代器关闭
// 写入对象数据到本地
return t.writeObjects(objIter)
}
// 将下载的对象写入本地文件系统。
// objIter: 下载中的对象迭代器。
// 返回值: 写入过程中可能出现的错误。
func (t *DownloadPackage) writeObjects(objIter iterator.DownloadingObjectIterator) error {
for {
objInfo, err := objIter.MoveNext()
if err == iterator.ErrNoMoreItem {
break // 没有更多对象时结束循环
}
if err != nil {
return err
}
err = func() error {
defer objInfo.File.Close() // 确保文件资源被释放
fullPath := filepath.Join(t.outputPath, objInfo.Object.Path) // 计算文件完整路径
dirPath := filepath.Dir(fullPath) // 获取文件所在目录路径
if err := os.MkdirAll(dirPath, 0755); err != nil { // 创建目录,如果不存在
return fmt.Errorf("creating object dir: %w", err)
}
outputFile, err := os.Create(fullPath) // 创建本地文件
if err != nil {
return fmt.Errorf("creating object file: %w", err)
}
defer outputFile.Close() // 确保文件关闭
_, err = io.Copy(outputFile, objInfo.File) // 将对象数据写入本地文件
if err != nil {
return fmt.Errorf("copy object data to local file failed, err: %w", err)
}
return nil
}()
if err != nil {
return err // 如果写入过程中出现错误,返回该错误
}
}
return nil // 没有错误返回nil
}