mirror of
https://github.com/halejohn/Cloudreve.git
synced 2026-01-26 09:34:57 +08:00
Feat: download torrent / multiple file / select file
This commit is contained in:
@@ -12,7 +12,6 @@ import (
|
||||
"github.com/HFO4/cloudreve/pkg/util"
|
||||
"github.com/zyxar/argo/rpc"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"time"
|
||||
@@ -110,7 +109,6 @@ func (monitor *Monitor) Update() bool {
|
||||
// UpdateTaskInfo 更新数据库中的任务信息
|
||||
func (monitor *Monitor) UpdateTaskInfo(status rpc.StatusInfo) error {
|
||||
originSize := monitor.Task.TotalSize
|
||||
originPath := monitor.Task.Path
|
||||
|
||||
monitor.Task.GID = status.Gid
|
||||
monitor.Task.Status = getStatus(status.Status)
|
||||
@@ -136,9 +134,6 @@ func (monitor *Monitor) UpdateTaskInfo(status rpc.StatusInfo) error {
|
||||
}
|
||||
|
||||
monitor.Task.Speed = speed
|
||||
if len(status.Files) > 0 {
|
||||
monitor.Task.Path = status.Files[0].Path
|
||||
}
|
||||
attrs, _ := json.Marshal(status)
|
||||
monitor.Task.Attrs = string(attrs)
|
||||
|
||||
@@ -146,8 +141,8 @@ func (monitor *Monitor) UpdateTaskInfo(status rpc.StatusInfo) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
if originSize != monitor.Task.TotalSize || originPath != monitor.Task.Path {
|
||||
// 大小、文件名更新后,对文件限制等进行校验
|
||||
if originSize != monitor.Task.TotalSize {
|
||||
// 文件大小更新后,对文件限制等进行校验
|
||||
if err := monitor.ValidateFile(); err != nil {
|
||||
// 验证失败时取消任务
|
||||
monitor.Cancel()
|
||||
@@ -190,19 +185,29 @@ func (monitor *Monitor) ValidateFile() error {
|
||||
// 创建上下文环境
|
||||
ctx := context.WithValue(context.Background(), fsctx.FileHeaderCtx, local.FileStream{
|
||||
Size: monitor.Task.TotalSize,
|
||||
Name: filepath.Base(monitor.Task.Path),
|
||||
})
|
||||
|
||||
// 验证文件
|
||||
if err := filesystem.HookValidateFile(ctx, fs); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 验证用户容量
|
||||
if err := filesystem.HookValidateCapacityWithoutIncrease(ctx, fs); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 验证每个文件
|
||||
for _, fileInfo := range monitor.Task.StatusInfo.Files {
|
||||
if fileInfo.Selected == "true" {
|
||||
// 创建上下文环境
|
||||
fileSize, _ := strconv.ParseUint(fileInfo.Length, 10, 64)
|
||||
ctx := context.WithValue(context.Background(), fsctx.FileHeaderCtx, local.FileStream{
|
||||
Size: fileSize,
|
||||
Name: filepath.Base(fileInfo.Path),
|
||||
})
|
||||
if err := filesystem.HookValidateFile(ctx, fs); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -216,21 +221,6 @@ func (monitor *Monitor) Error(status rpc.StatusInfo) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// RemoveTempFile 清理下载临时文件
|
||||
func (monitor *Monitor) RemoveTempFile() {
|
||||
err := os.Remove(monitor.Task.Path)
|
||||
if err != nil {
|
||||
util.Log().Warning("无法删除离线下载临时文件[%s], %s", monitor.Task.Path, err)
|
||||
}
|
||||
|
||||
if empty, _ := util.IsEmpty(monitor.Task.Parent); empty {
|
||||
err := os.Remove(monitor.Task.Parent)
|
||||
if err != nil {
|
||||
util.Log().Warning("无法删除离线下载临时目录[%s], %s", monitor.Task.Parent, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// RemoveTempFolder 清理下载临时目录
|
||||
func (monitor *Monitor) RemoveTempFolder() {
|
||||
err := os.RemoveAll(monitor.Task.Parent)
|
||||
@@ -243,10 +233,16 @@ func (monitor *Monitor) RemoveTempFolder() {
|
||||
// Complete 完成下载,返回是否中断监控
|
||||
func (monitor *Monitor) Complete(status rpc.StatusInfo) bool {
|
||||
// 创建中转任务
|
||||
file := make([]string, 0, len(monitor.Task.StatusInfo.Files))
|
||||
for i := 0; i < len(monitor.Task.StatusInfo.Files); i++ {
|
||||
if monitor.Task.StatusInfo.Files[i].Selected == "true" {
|
||||
file = append(file, monitor.Task.StatusInfo.Files[i].Path)
|
||||
}
|
||||
}
|
||||
job, err := task.NewTransferTask(
|
||||
monitor.Task.UserID,
|
||||
path.Join(monitor.Task.Dst, filepath.Base(monitor.Task.Path)),
|
||||
monitor.Task.Path,
|
||||
file,
|
||||
monitor.Task.Dst,
|
||||
monitor.Task.Parent,
|
||||
)
|
||||
if err != nil {
|
||||
|
||||
@@ -22,6 +22,8 @@ type Aria2 interface {
|
||||
Status(task *model.Download) (rpc.StatusInfo, error)
|
||||
// 取消任务
|
||||
Cancel(task *model.Download) error
|
||||
// 选择要下载的文件
|
||||
Select(task *model.Download, files []int) error
|
||||
}
|
||||
|
||||
const (
|
||||
@@ -73,6 +75,11 @@ func (instance *DummyAria2) Cancel(task *model.Download) error {
|
||||
return ErrNotEnabled
|
||||
}
|
||||
|
||||
// Select 返回未开启错误
|
||||
func (instance *DummyAria2) Select(task *model.Download, files []int) error {
|
||||
return ErrNotEnabled
|
||||
}
|
||||
|
||||
// Init 初始化
|
||||
func Init() {
|
||||
options := model.GetSettingByNames("aria2_rpcurl", "aria2_token", "aria2_options")
|
||||
|
||||
@@ -3,9 +3,11 @@ package aria2
|
||||
import (
|
||||
"context"
|
||||
model "github.com/HFO4/cloudreve/models"
|
||||
"github.com/HFO4/cloudreve/pkg/util"
|
||||
"github.com/zyxar/argo/rpc"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
@@ -46,20 +48,32 @@ func (client *RPCService) Cancel(task *model.Download) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// Select 选取要下载的文件
|
||||
func (client *RPCService) Select(task *model.Download, files []int) error {
|
||||
var selected = make([]string, len(files))
|
||||
for i := 0; i < len(files); i++ {
|
||||
selected[i] = strconv.Itoa(files[i])
|
||||
}
|
||||
ok, err := client.caller.ChangeOption(task.GID, map[string]interface{}{"select-file": strings.Join(selected, ",")})
|
||||
util.Log().Debug(ok)
|
||||
return err
|
||||
}
|
||||
|
||||
// CreateTask 创建新任务
|
||||
func (client *RPCService) CreateTask(task *model.Download) error {
|
||||
// 生成存储路径
|
||||
task.Path = filepath.Join(
|
||||
path := filepath.Join(
|
||||
model.GetSettingByName("aria2_temp_path"),
|
||||
"aria2",
|
||||
strconv.FormatInt(time.Now().UnixNano(), 10),
|
||||
)
|
||||
|
||||
// 创建下载任务
|
||||
options := []interface{}{map[string]string{"dir": task.Path}}
|
||||
options := []interface{}{map[string]string{"dir": path}}
|
||||
if len(client.options.Options) > 0 {
|
||||
options = append(options, client.options.Options)
|
||||
}
|
||||
|
||||
gid, err := client.caller.AddURI(task.Source, options...)
|
||||
if err != nil || gid == "" {
|
||||
return err
|
||||
|
||||
@@ -501,6 +501,7 @@ func (client *Client) request(ctx context.Context, method string, url string, bo
|
||||
)
|
||||
|
||||
if res.Err != nil {
|
||||
// TODO 重试
|
||||
return "", sysError(res.Err)
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,8 @@ import (
|
||||
"github.com/HFO4/cloudreve/pkg/filesystem"
|
||||
"github.com/HFO4/cloudreve/pkg/util"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
// TransferTask 文件中转任务
|
||||
@@ -21,9 +23,9 @@ type TransferTask struct {
|
||||
|
||||
// TransferProps 中转任务属性
|
||||
type TransferProps struct {
|
||||
Src string `json:"src"` // 原始目录
|
||||
Parent string `json:"parent"` // 父目录
|
||||
Dst string `json:"dst"` // 目的目录ID
|
||||
Src []string `json:"src"` // 原始目录
|
||||
Parent string `json:"parent"` // 父目录
|
||||
Dst string `json:"dst"` // 目的目录ID
|
||||
}
|
||||
|
||||
// Props 获取任务属性
|
||||
@@ -86,30 +88,26 @@ func (job *TransferTask) Do() {
|
||||
}
|
||||
defer fs.Recycle()
|
||||
|
||||
err = fs.UploadFromPath(context.Background(), job.TaskProps.Src, job.TaskProps.Dst)
|
||||
if err != nil {
|
||||
job.SetErrorMsg("文件转存失败", err)
|
||||
return
|
||||
for _, file := range job.TaskProps.Src {
|
||||
err = fs.UploadFromPath(context.Background(), file, path.Join(job.TaskProps.Dst, filepath.Base(file)))
|
||||
if err != nil {
|
||||
job.SetErrorMsg("文件转存失败", err)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Recycle 回收临时文件
|
||||
func (job *TransferTask) Recycle() {
|
||||
err := os.Remove(job.TaskProps.Src)
|
||||
err := os.RemoveAll(job.TaskProps.Parent)
|
||||
if err != nil {
|
||||
util.Log().Warning("无法删除中转临时文件[%s], %s", job.TaskProps.Src, err)
|
||||
util.Log().Warning("无法删除中转临时目录[%s], %s", job.TaskProps.Parent, err)
|
||||
}
|
||||
|
||||
if empty, _ := util.IsEmpty(job.TaskProps.Parent); empty {
|
||||
err := os.Remove(job.TaskProps.Parent)
|
||||
if err != nil {
|
||||
util.Log().Warning("无法删除中转临时目录[%s], %s", job.TaskProps.Parent, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// NewTransferTask 新建中转任务
|
||||
func NewTransferTask(user uint, dst, src, parent string) (Job, error) {
|
||||
func NewTransferTask(user uint, src []string, dst, parent string) (Job, error) {
|
||||
creator, err := model.GetUserByID(user)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
Reference in New Issue
Block a user