mirror of
https://github.com/tickstep/aliyunpan.git
synced 2025-01-23 22:42:15 +08:00
add download file plugin hook
This commit is contained in:
parent
5572f844ed
commit
a318796f3b
77
assets/plugin/js/download_handler.js
Executable file
77
assets/plugin/js/download_handler.js
Executable file
@ -0,0 +1,77 @@
|
||||
// ==========================================================================================
|
||||
// aliyunpan JS插件回调处理函数
|
||||
// 支持 JavaScript ECMAScript 5.1 语言规范
|
||||
//
|
||||
// 更多内容请查看官方文档:https://github.com/tickstep/aliyunpan
|
||||
// ==========================================================================================
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------
|
||||
// 函数说明:下载文件前的回调函数
|
||||
//
|
||||
// 参数说明
|
||||
// context - 当前调用的上下文信息
|
||||
// {
|
||||
// "appName": "aliyunpan",
|
||||
// "version": "v0.1.3",
|
||||
// "userId": "11001d48564f43b3bc5662874f04bb11",
|
||||
// "nickname": "tickstep",
|
||||
// "fileDriveId": "19519111",
|
||||
// "albumDriveId": "29519122"
|
||||
// }
|
||||
// appName - 应用名称,当前固定为aliyunpan
|
||||
// version - 版本号
|
||||
// userId - 当前登录用户的ID
|
||||
// nickname - 用户昵称
|
||||
// fileDriveId - 用户文件网盘ID
|
||||
// albumDriveId - 用户相册网盘ID
|
||||
//
|
||||
// params - 文件下载前参数
|
||||
// {
|
||||
// "driveId": "19519221",
|
||||
// "driveFileName": "token.bat",
|
||||
// "driveFilePath": "aliyunpan/Downloads/token.bat",
|
||||
// "driveFileSha1": "08FBE28A5B8791A2F50225E2EC5CEEC3C7955A11",
|
||||
// "driveFileSize": 125330,
|
||||
// "driveFileType": "file",
|
||||
// "driveFileUpdatedAt": "2022-04-14 07:05:12",
|
||||
// "localFilePath": "aliyunpan\\Downloads\\token.bat"
|
||||
// }
|
||||
// driveId - 网盘ID
|
||||
// driveFileName - 网盘文件名
|
||||
// driveFilePath - 网盘文件绝对完整路径
|
||||
// driveFileSize - 网盘文件大小,单位B
|
||||
// driveFileSha1 - 网盘文件SHA1
|
||||
// driveFileType - 网盘文件类型,file-文件,folder-文件夹
|
||||
// driveFileUpdatedAt - 网盘文件修改时间
|
||||
// localFilePath - 下载文件到本地保存的路径,这个是相对路径,相对指定下载的目标文件夹
|
||||
//
|
||||
// 返回值说明
|
||||
// {
|
||||
// "downloadApproved": "yes",
|
||||
// "localFilePath": "newfolder\\token.bat"
|
||||
// }
|
||||
// downloadApproved - 该文件是否下载,yes-确认下载,no-取消下载
|
||||
// localFilePath - 文件保存的本地路径,这个是相对路径,如果为空""代表保持原本的目标路径。
|
||||
// 这个改动要小心,会导致重名文件下载只会下载一个
|
||||
// ------------------------------------------------------------------------------------------
|
||||
function downloadFilePrepareCallback(context, params) {
|
||||
console.log(params)
|
||||
|
||||
var result = {
|
||||
"downloadApproved": "yes",
|
||||
"localFilePath": ""
|
||||
};
|
||||
|
||||
// 所有的.dmg.exe文件,下载保存的文件后缀名去掉.exe,网盘文件不改动
|
||||
if (params["driveFileName"].lastIndexOf(".dmg.exe") > 0) {
|
||||
result["localFilePath"] = params["localFilePath"].substr(0, (params["localFilePath"].length - ".exe".length));
|
||||
}
|
||||
|
||||
// 禁止.txt文件下载
|
||||
if (params["driveFileName"].lastIndexOf(".txt") > 0) {
|
||||
result["downloadApproved"] = "no";
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
@ -51,7 +51,7 @@
|
||||
// }
|
||||
// uploadApproved - 该文件是否确认上传,yes-允许上传,no-禁止上传
|
||||
// driveFilePath - 文件保存的网盘路径,这个是相对路径,如果为空""代表保持原本的目标路径。
|
||||
// 这个改动要小心,会导致重名文件上传失败
|
||||
// 这个改动要小心,会导致重名文件只会上传一个
|
||||
// ------------------------------------------------------------------------------------------
|
||||
function uploadFilePrepareCallback(context, params) {
|
||||
var result = {
|
||||
|
@ -19,13 +19,15 @@ import (
|
||||
"github.com/tickstep/aliyunpan-api/aliyunpan"
|
||||
"github.com/tickstep/aliyunpan-api/aliyunpan/apierror"
|
||||
"github.com/tickstep/aliyunpan/cmder/cmdtable"
|
||||
"github.com/tickstep/aliyunpan/internal/config"
|
||||
"github.com/tickstep/aliyunpan/internal/file/downloader"
|
||||
"github.com/tickstep/aliyunpan/internal/functions"
|
||||
"github.com/tickstep/aliyunpan/internal/plugins"
|
||||
"github.com/tickstep/aliyunpan/internal/taskframework"
|
||||
"github.com/tickstep/aliyunpan/library/requester/transfer"
|
||||
"github.com/tickstep/library-go/converter"
|
||||
"github.com/tickstep/library-go/logger"
|
||||
"github.com/tickstep/library-go/requester"
|
||||
"github.com/tickstep/aliyunpan/library/requester/transfer"
|
||||
"github.com/tickstep/library-go/requester/rio/speeds"
|
||||
"io"
|
||||
"net/http"
|
||||
@ -47,7 +49,7 @@ type (
|
||||
ParentTaskExecutor *taskframework.TaskExecutor
|
||||
|
||||
DownloadStatistic *DownloadStatistic // 下载统计
|
||||
GlobalSpeedsStat *speeds.Speeds // 全局速度统计
|
||||
GlobalSpeedsStat *speeds.Speeds // 全局速度统计
|
||||
|
||||
// 可选项
|
||||
VerbosePrinter *logger.CmdVerbose
|
||||
@ -57,10 +59,10 @@ type (
|
||||
IsOverwrite bool // 是否覆盖已存在的文件
|
||||
NoCheck bool // 不校验文件
|
||||
|
||||
FilePanPath string // 要下载的网盘文件路径
|
||||
SavePath string // 文件保存在本地的路径
|
||||
OriginSaveRootPath string // 文件保存在本地的根目录路径
|
||||
DriveId string
|
||||
FilePanPath string // 要下载的网盘文件路径
|
||||
SavePath string // 文件保存在本地的路径
|
||||
OriginSaveRootPath string // 文件保存在本地的根目录路径
|
||||
DriveId string
|
||||
|
||||
fileInfo *aliyunpan.FileEntity // 文件或目录详情
|
||||
}
|
||||
@ -145,12 +147,12 @@ func (dtu *DownloadTaskUnit) download() (err error) {
|
||||
if dtu.IsPrintStatus {
|
||||
// 输出所有的worker状态
|
||||
var (
|
||||
tb = cmdtable.NewTable(builder)
|
||||
tb = cmdtable.NewTable(builder)
|
||||
)
|
||||
tb.SetHeader([]string{"#", "status", "range", "left", "speeds", "error"})
|
||||
workersCallback(func(key int, worker *downloader.Worker) bool {
|
||||
wrange := worker.GetRange()
|
||||
tb.Append([]string{fmt.Sprint(worker.ID()), worker.GetStatus().StatusText(), wrange.ShowDetails(), strconv.FormatInt(wrange.Len(), 10), converter.ConvertFileSize(worker.GetSpeedsPerSecond(), 2)+"/s", fmt.Sprint(worker.Err())})
|
||||
tb.Append([]string{fmt.Sprint(worker.ID()), worker.GetStatus().StatusText(), wrange.ShowDetails(), strconv.FormatInt(wrange.Len(), 10), converter.ConvertFileSize(worker.GetSpeedsPerSecond(), 2) + "/s", fmt.Sprint(worker.Err())})
|
||||
return true
|
||||
})
|
||||
|
||||
@ -270,7 +272,7 @@ func (dtu *DownloadTaskUnit) handleError(result *taskframework.TaskUnitRunResult
|
||||
result.NeedRetry = true
|
||||
}
|
||||
}
|
||||
time.Sleep(1*time.Second)
|
||||
time.Sleep(1 * time.Second)
|
||||
}
|
||||
|
||||
//checkFileValid 检测文件有效性
|
||||
@ -343,6 +345,10 @@ func (dtu *DownloadTaskUnit) OnFailed(lastRunResult *taskframework.TaskUnitRunRe
|
||||
func (dtu *DownloadTaskUnit) OnComplete(lastRunResult *taskframework.TaskUnitRunResult) {
|
||||
}
|
||||
|
||||
func (dtu *DownloadTaskUnit) OnCancel(lastRunResult *taskframework.TaskUnitRunResult) {
|
||||
|
||||
}
|
||||
|
||||
func (dtu *DownloadTaskUnit) RetryWait() time.Duration {
|
||||
return functions.RetryWait(dtu.taskInfo.Retry())
|
||||
}
|
||||
@ -363,7 +369,7 @@ func (dtu *DownloadTaskUnit) Run() (result *taskframework.TaskUnitRunResult) {
|
||||
dtu.handleError(result)
|
||||
return
|
||||
}
|
||||
time.Sleep(1*time.Second)
|
||||
time.Sleep(1 * time.Second)
|
||||
}
|
||||
|
||||
// 输出文件信息
|
||||
@ -378,15 +384,15 @@ func (dtu *DownloadTaskUnit) Run() (result *taskframework.TaskUnitRunResult) {
|
||||
}
|
||||
|
||||
// 获取该目录下的文件列表
|
||||
fileList,apierr := dtu.PanClient.FileListGetAll(&aliyunpan.FileListParam{
|
||||
fileList, apierr := dtu.PanClient.FileListGetAll(&aliyunpan.FileListParam{
|
||||
DriveId: dtu.DriveId,
|
||||
ParentFileId: dtu.fileInfo.FileId,
|
||||
})
|
||||
if apierr != nil {
|
||||
// retry one more time
|
||||
time.Sleep(3*time.Second)
|
||||
time.Sleep(3 * time.Second)
|
||||
|
||||
fileList,apierr = dtu.PanClient.FileListGetAll(&aliyunpan.FileListParam{
|
||||
fileList, apierr = dtu.PanClient.FileListGetAll(&aliyunpan.FileListParam{
|
||||
DriveId: dtu.DriveId,
|
||||
ParentFileId: dtu.fileInfo.FileId,
|
||||
})
|
||||
@ -408,7 +414,7 @@ func (dtu *DownloadTaskUnit) Run() (result *taskframework.TaskUnitRunResult) {
|
||||
result.NeedRetry = true
|
||||
return
|
||||
}
|
||||
time.Sleep(1*time.Second)
|
||||
time.Sleep(1 * time.Second)
|
||||
|
||||
// 创建对应的任务进行下载
|
||||
for k := range fileList {
|
||||
@ -436,6 +442,37 @@ func (dtu *DownloadTaskUnit) Run() (result *taskframework.TaskUnitRunResult) {
|
||||
return
|
||||
}
|
||||
|
||||
// 调用插件
|
||||
pluginManger := plugins.NewPluginManager(config.GetPluginDir())
|
||||
plugin, _ := pluginManger.GetPlugin()
|
||||
localFilePath := strings.TrimPrefix(dtu.SavePath, dtu.OriginSaveRootPath)
|
||||
localFilePath = strings.TrimPrefix(strings.TrimPrefix(localFilePath, "\\"), "/")
|
||||
pluginParam := &plugins.DownloadFilePrepareParams{
|
||||
DriveId: dtu.fileInfo.DriveId,
|
||||
DriveFilePath: dtu.fileInfo.Path,
|
||||
DriveFileName: dtu.fileInfo.FileName,
|
||||
DriveFileSize: dtu.fileInfo.FileSize,
|
||||
DriveFileType: "file",
|
||||
DriveFileSha1: dtu.fileInfo.ContentHash,
|
||||
DriveFileUpdatedAt: dtu.fileInfo.UpdatedAt,
|
||||
LocalFilePath: localFilePath,
|
||||
}
|
||||
if downloadFilePrepareResult, er := plugin.DownloadFilePrepareCallback(plugins.GetContext(config.Config.ActiveUser()), pluginParam); er == nil && downloadFilePrepareResult != nil {
|
||||
if strings.Compare("yes", downloadFilePrepareResult.DownloadApproved) != 0 {
|
||||
// skip download this file
|
||||
fmt.Printf("插件取消了该文件下载: %s\n", dtu.fileInfo.Path)
|
||||
result.Succeed = false
|
||||
result.Cancel = true
|
||||
return
|
||||
}
|
||||
if downloadFilePrepareResult.LocalFilePath != "" {
|
||||
targetSaveRelativePath := strings.TrimPrefix(downloadFilePrepareResult.LocalFilePath, "/")
|
||||
targetSaveRelativePath = strings.TrimPrefix(targetSaveRelativePath, "\\")
|
||||
dtu.SavePath = path.Clean(dtu.OriginSaveRootPath + string(os.PathSeparator) + targetSaveRelativePath)
|
||||
fmt.Printf("插件修改文件下载保存路径为: %s\n", dtu.SavePath)
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Printf("[%s] 准备下载: %s\n", dtu.taskInfo.Id(), dtu.FilePanPath)
|
||||
|
||||
if !dtu.IsOverwrite && FileExist(dtu.SavePath) {
|
||||
|
@ -294,7 +294,9 @@ var ResultUpdateLocalDatabase = &taskframework.TaskUnitRunResult{ResultCode: 2,
|
||||
func (utu *UploadTaskUnit) OnComplete(lastRunResult *taskframework.TaskUnitRunResult) {
|
||||
// 任务结束,可能成功也可能失败
|
||||
}
|
||||
func (utu *UploadTaskUnit) OnCancel(lastRunResult *taskframework.TaskUnitRunResult) {
|
||||
|
||||
}
|
||||
func (utu *UploadTaskUnit) RetryWait() time.Duration {
|
||||
return functions.RetryWait(utu.taskInfo.Retry())
|
||||
}
|
||||
|
@ -20,6 +20,10 @@ func (p *IdlePlugin) UploadFilePrepareCallback(context *Context, params *UploadF
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (p *IdlePlugin) DownloadFilePrepareCallback(context *Context, params *DownloadFilePrepareParams) (*DownloadFilePrepareResult, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (p *IdlePlugin) Stop() error {
|
||||
return nil
|
||||
}
|
||||
|
@ -105,6 +105,25 @@ func (js *JsPlugin) UploadFileFinishCallback(context *Context, params *UploadFil
|
||||
return nil
|
||||
}
|
||||
|
||||
// DownloadFilePrepareCallback 下载文件前的回调函数
|
||||
func (js *JsPlugin) DownloadFilePrepareCallback(context *Context, params *DownloadFilePrepareParams) (*DownloadFilePrepareResult, error) {
|
||||
var fn func(*Context, *DownloadFilePrepareParams) (*DownloadFilePrepareResult, error)
|
||||
if !js.isHandlerFuncExisted("downloadFilePrepareCallback") {
|
||||
return nil, nil
|
||||
}
|
||||
err := js.vm.ExportTo(js.vm.Get("downloadFilePrepareCallback"), &fn)
|
||||
if err != nil {
|
||||
logger.Verboseln("Js函数映射到 Go 函数失败!")
|
||||
return nil, nil
|
||||
}
|
||||
r, er := fn(context, params)
|
||||
if er != nil {
|
||||
logger.Verboseln(er)
|
||||
return nil, er
|
||||
}
|
||||
return r, nil
|
||||
}
|
||||
|
||||
func (js *JsPlugin) Stop() error {
|
||||
return nil
|
||||
}
|
||||
|
@ -56,6 +56,26 @@ type (
|
||||
DriveFilePath string `json:"driveFilePath"`
|
||||
}
|
||||
|
||||
// DownloadFilePrepareParams 下载文件前的回调函数-参数
|
||||
DownloadFilePrepareParams struct {
|
||||
DriveId string `json:"driveId"`
|
||||
DriveFileName string `json:"driveFileName"`
|
||||
DriveFilePath string `json:"driveFilePath"`
|
||||
DriveFileSha1 string `json:"driveFileSha1"`
|
||||
DriveFileSize int64 `json:"driveFileSize"`
|
||||
DriveFileType string `json:"driveFileType"`
|
||||
DriveFileUpdatedAt string `json:"driveFileUpdatedAt"`
|
||||
LocalFilePath string `json:"localFilePath"`
|
||||
}
|
||||
|
||||
// DownloadFilePrepareResult 上传文件前的回调函数-返回结果
|
||||
DownloadFilePrepareResult struct {
|
||||
// DownloadApproved 确认该文件是否下载。yes-下载 no-不下载
|
||||
DownloadApproved string `json:"downloadApproved"`
|
||||
// LocalFilePath 保存本地的修改后的路径。注意该路径是相对路径
|
||||
LocalFilePath string `json:"localFilePath"`
|
||||
}
|
||||
|
||||
// Plugin 插件接口
|
||||
Plugin interface {
|
||||
// Start 启动
|
||||
@ -67,6 +87,9 @@ type (
|
||||
// UploadFileFinishCallback 上传文件完成的回调函数
|
||||
UploadFileFinishCallback(context *Context, params *UploadFileFinishParams) error
|
||||
|
||||
// DownloadFilePrepareCallback 下载文件前的回调函数
|
||||
DownloadFilePrepareCallback(context *Context, params *DownloadFilePrepareParams) (*DownloadFilePrepareResult, error)
|
||||
|
||||
// Stop 停止
|
||||
Stop() error
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestPlugin(t *testing.T) {
|
||||
func TestPluginUpload(t *testing.T) {
|
||||
pluginManager := NewPluginManager("D:\\smb\\feny\\goprojects\\dev")
|
||||
plugin, err := pluginManager.GetPlugin()
|
||||
if err != nil {
|
||||
@ -39,3 +39,38 @@ func TestPlugin(t *testing.T) {
|
||||
}
|
||||
fmt.Println(r)
|
||||
}
|
||||
|
||||
func TestPluginDownload(t *testing.T) {
|
||||
pluginManager := NewPluginManager("/Volumes/Downloads/dev/config/plugin")
|
||||
plugin, err := pluginManager.GetPlugin()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
ctx := &Context{
|
||||
AppName: "aliyunpan",
|
||||
Version: "v0.1.3",
|
||||
UserId: "11001d48564f43b3bc5662874f04bb11",
|
||||
Nickname: "tickstep",
|
||||
FileDriveId: "19519121",
|
||||
AlbumDriveId: "29519122",
|
||||
}
|
||||
params := &DownloadFilePrepareParams{
|
||||
DriveId: "19519221",
|
||||
DriveFilePath: "/test/aliyunpan/Downloads/token.bat",
|
||||
DriveFileName: "token.bat",
|
||||
DriveFileSize: 125330,
|
||||
DriveFileType: "file",
|
||||
DriveFileSha1: "08FBE28A5B8791A2F50225E2EC5CEEC3C7955A11",
|
||||
DriveFileUpdatedAt: "2022-04-14 07:05:12",
|
||||
LocalFilePath: "aliyunpan\\Downloads\\token.bat",
|
||||
}
|
||||
b, _ := jsoniter.Marshal(ctx)
|
||||
fmt.Println(string(b))
|
||||
b, _ = jsoniter.Marshal(params)
|
||||
fmt.Println(string(b))
|
||||
r, e := plugin.DownloadFilePrepareCallback(ctx, params)
|
||||
if e != nil {
|
||||
fmt.Println(e)
|
||||
}
|
||||
fmt.Println(r)
|
||||
}
|
||||
|
@ -116,6 +116,12 @@ func (te *TaskExecutor) Execute() {
|
||||
return
|
||||
}
|
||||
|
||||
// 取消下载
|
||||
if result.Cancel {
|
||||
task.Unit.OnCancel(result)
|
||||
return
|
||||
}
|
||||
|
||||
if result.Succeed {
|
||||
task.Unit.OnSuccess(result)
|
||||
task.Unit.OnComplete(result)
|
||||
|
@ -29,14 +29,17 @@ type (
|
||||
OnFailed(lastRunResult *TaskUnitRunResult)
|
||||
// 每次执行结束执行的方法, 不管成功失败
|
||||
OnComplete(lastRunResult *TaskUnitRunResult)
|
||||
// 取消下载
|
||||
OnCancel(lastRunResult *TaskUnitRunResult)
|
||||
// 重试等待的时间
|
||||
RetryWait() time.Duration
|
||||
}
|
||||
|
||||
// 任务单元执行结果
|
||||
TaskUnitRunResult struct {
|
||||
Succeed bool // 是否执行成功
|
||||
NeedRetry bool // 是否需要重试
|
||||
Succeed bool // 是否执行成功
|
||||
NeedRetry bool // 是否需要重试
|
||||
Cancel bool // 是否取消了任务
|
||||
|
||||
// 以下是额外的信息
|
||||
Err error // 错误信息
|
||||
|
@ -51,6 +51,10 @@ func (tu *TestUnit) Run() (result *taskframework.TaskUnitRunResult) {
|
||||
}
|
||||
}
|
||||
|
||||
func (tu *TestUnit) OnCancel(lastRunResult *taskframework.TaskUnitRunResult) {
|
||||
|
||||
}
|
||||
|
||||
func (tu *TestUnit) OnRetry(lastRunResult *taskframework.TaskUnitRunResult) {
|
||||
fmt.Printf("[%s] prepare retry, times [%d/%d]...\n", tu.taskInfo.Id(), tu.taskInfo.Retry(), tu.taskInfo.MaxRetry())
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user