You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

ipfs_read.go 3.2 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. package task
  2. import (
  3. "fmt"
  4. "io"
  5. "os"
  6. "path/filepath"
  7. "time"
  8. "gitlink.org.cn/cloudream/common/pkgs/logger"
  9. "gitlink.org.cn/cloudream/common/pkgs/task"
  10. stgglb "gitlink.org.cn/cloudream/storage/common/globals"
  11. )
  12. // IPFSRead 代表从IPFS读取文件的任务
  13. type IPFSRead struct {
  14. FileHash string // 文件的IPFS哈希值
  15. LocalPath string // 本地存储路径
  16. }
  17. // NewIPFSRead 创建一个新的IPFS读取任务实例
  18. func NewIPFSRead(fileHash string, localPath string) *IPFSRead {
  19. return &IPFSRead{
  20. FileHash: fileHash,
  21. LocalPath: localPath,
  22. }
  23. }
  24. // Compare 比较当前任务与另一个任务是否相同
  25. // other: 要比较的另一个任务
  26. // 返回值: 如果两个任务相同返回true,否则返回false
  27. func (t *IPFSRead) Compare(other *Task) bool {
  28. tsk, ok := other.Body().(*IPFSRead)
  29. if !ok {
  30. return false
  31. }
  32. return t.FileHash == tsk.FileHash && t.LocalPath == tsk.LocalPath
  33. }
  34. // Execute 执行从IPFS读取文件并存储到本地的任务
  35. // task: 任务实例
  36. // ctx: 任务上下文
  37. // complete: 任务完成的回调函数
  38. func (t *IPFSRead) Execute(task *task.Task[TaskContext], ctx TaskContext, complete CompleteFn) {
  39. // 初始化日志
  40. log := logger.WithType[IPFSRead]("Task")
  41. log.Debugf("begin with %v", logger.FormatStruct(t))
  42. defer log.Debugf("end")
  43. // 获取输出文件的目录并创建该目录
  44. outputFileDir := filepath.Dir(t.LocalPath)
  45. // 创建输出文件的目录
  46. err := os.MkdirAll(outputFileDir, os.ModePerm)
  47. if err != nil {
  48. // 目录创建失败的处理
  49. err := fmt.Errorf("create output file directory %s failed, err: %w", outputFileDir, err)
  50. log.WithField("LocalPath", t.LocalPath).Warn(err.Error())
  51. complete(err, CompleteOption{
  52. RemovingDelay: time.Minute,
  53. })
  54. return
  55. }
  56. // 创建输出文件
  57. outputFile, err := os.Create(t.LocalPath)
  58. if err != nil {
  59. // 输出文件创建失败的处理
  60. err := fmt.Errorf("create output file %s failed, err: %w", t.LocalPath, err)
  61. log.WithField("LocalPath", t.LocalPath).Warn(err.Error())
  62. complete(err, CompleteOption{
  63. RemovingDelay: time.Minute,
  64. })
  65. return
  66. }
  67. defer outputFile.Close()
  68. // 获取IPFS客户端
  69. ipfsCli, err := stgglb.IPFSPool.Acquire()
  70. if err != nil {
  71. // 获取IPFS客户端失败的处理
  72. err := fmt.Errorf("new ipfs client: %w", err)
  73. log.Warn(err.Error())
  74. complete(err, CompleteOption{
  75. RemovingDelay: time.Minute,
  76. })
  77. return
  78. }
  79. defer ipfsCli.Close()
  80. // 打开IPFS中的文件进行读取
  81. rd, err := ipfsCli.OpenRead(t.FileHash)
  82. if err != nil {
  83. // 打开IPFS文件失败的处理
  84. err := fmt.Errorf("read ipfs file failed, err: %w", err)
  85. log.WithField("FileHash", t.FileHash).Warn(err.Error())
  86. complete(err, CompleteOption{
  87. RemovingDelay: time.Minute,
  88. })
  89. return
  90. }
  91. // 将IPFS文件内容复制到本地文件
  92. _, err = io.Copy(outputFile, rd)
  93. if err != nil {
  94. // 文件复制失败的处理
  95. err := fmt.Errorf("copy ipfs file to local file failed, err: %w", err)
  96. log.WithField("LocalPath", t.LocalPath).Warn(err.Error())
  97. complete(err, CompleteOption{
  98. RemovingDelay: time.Minute,
  99. })
  100. return
  101. }
  102. // 任务完成,调用回调函数
  103. complete(nil, CompleteOption{
  104. RemovingDelay: time.Minute,
  105. })
  106. }

本项目旨在将云际存储公共基础设施化,使个人及企业可低门槛使用高效的云际存储服务(安装开箱即用云际存储客户端即可,无需关注其他组件的部署),同时支持用户灵活便捷定制云际存储的功能细节。