mirror of
https://gitee.com/zhangsken/aliyunpan.git
synced 2026-10-16 10:29:42 +08:00
Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d05d19acd8 | |||
| 5179f914ed | |||
| 2feaa3cf82 | |||
| cedd43d402 | |||
| e62bdbb9f1 | |||
| acc408f0a0 |
@@ -66,9 +66,9 @@
|
||||
|
||||
参考例子:
|
||||
```shell
|
||||
wget https://github.com/tickstep/aliyunpan/releases/download/v0.3.9/aliyunpan-v0.3.9-linux-amd64.zip
|
||||
unzip aliyunpan-v0.3.9-linux-amd64.zip
|
||||
cd aliyunpan-v0.3.9-linux-amd64
|
||||
wget https://github.com/tickstep/aliyunpan/releases/download/v0.4.0/aliyunpan-v0.4.0-linux-amd64.zip
|
||||
unzip aliyunpan-v0.4.0-linux-amd64.zip
|
||||
cd aliyunpan-v0.4.0-linux-amd64
|
||||
./aliyunpan
|
||||
```
|
||||
|
||||
@@ -107,7 +107,7 @@ winget source update
|
||||
```
|
||||
安装
|
||||
```powershell
|
||||
winget install tickstep.aliyunpan --silent
|
||||
winget install tickstep.aliyunpan --source winget --silent
|
||||
|
||||
```
|
||||
|
||||
@@ -126,7 +126,7 @@ winget install tickstep.aliyunpan --silent
|
||||

|
||||
|
||||
```
|
||||
docker run -d --name=aliyunpan-sync --restart=always -v "<your aliyunpan_config.json>:/home/app/config/aliyunpan_config.json" -v "<your local dir>:/home/app/data" -e ALIYUNPAN_PAN_DIR="<your drive pan dir>" -e ALIYUNPAN_SYNC_MODE="upload" -e ALIYUNPAN_SYNC_POLICY="increment" -e ALIYUNPAN_SYNC_DRIVE="backup" -e ALIYUNPAN_SYNC_LOG="true" tickstep/aliyunpan-sync:v0.3.9
|
||||
docker run -d --name=aliyunpan-sync --restart=always -v "<your aliyunpan_config.json>:/home/app/config/aliyunpan_config.json" -v "<your local dir>:/home/app/data" -e ALIYUNPAN_PAN_DIR="<your drive pan dir>" -e ALIYUNPAN_SYNC_MODE="upload" -e ALIYUNPAN_SYNC_POLICY="increment" -e ALIYUNPAN_SYNC_DRIVE="backup" -e ALIYUNPAN_SYNC_LOG="true" tickstep/aliyunpan-sync:v0.4.0
|
||||
|
||||
<your aliyunpan_config.json>: 用户已经登录成功并保存好的aliyunpan_config.json凭据文件
|
||||
<your local dir>:本地目标目录,绝对路径,例如:/tickstep/Documents/设计文档
|
||||
@@ -241,7 +241,7 @@ aliyunpan:/ tickstep$ ls
|
||||
```
|
||||
|
||||
### 下载文件
|
||||
通过 `aliyunpan config set -savedir <savedir>` 可以自定义下载文件保存的目录。
|
||||
如果需要更改默认下载目录路径,可以通过 `aliyunpan config set -savedir <savedir>` 自定义下载文件保存的目录。
|
||||
```shell
|
||||
aliyunpan:/ tickstep$ download IMG_0106.JPG
|
||||
|
||||
@@ -320,7 +320,7 @@ aliyunpan:/ tickstep$ upload /Users/tickstep/Downloads /photo -ui
|
||||
```
|
||||
|
||||
### 同步备份文件
|
||||
同步备份功能,支持备份本地文件到云盘,备份云盘文件到本地,双向同步备份三种模式。支持JavaScript插件对备份文件进行过滤。
|
||||
同步备份功能,支持备份本地文件到云盘,备份云盘文件到本地两种模式。支持JavaScript插件对备份文件进行过滤。
|
||||
|
||||
例如:将本地目录 `/tickstep/Documents/设计文档` 中的文件备份上传到云盘目录 `/备份盘/我的文档`
|
||||
```shell
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
|
||||
<assemblyIdentity version="0.3.9.0" processorArchitecture="*" name="com.tickstep.aliyunpan" type="win32"/>
|
||||
<assemblyIdentity version="0.4.0.0" processorArchitecture="*" name="com.tickstep.aliyunpan" type="win32"/>
|
||||
<dependency>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="*" publicKeyToken="6595b64144ccf1df" language="*"/>
|
||||
|
||||
+26
-10
@@ -343,20 +343,36 @@ aliyunpan upload -exn "\.jpg$" -exn "\.mp3$" C:/Users/Administrator/Video /视
|
||||
```
|
||||
#!/bin/bash
|
||||
|
||||
# 是否开启调试日志
|
||||
# 是否开启调试日志 (1=开启, 0=关闭)
|
||||
export ALIYUNPAN_VERBOSE=0
|
||||
# (可选)配置目录的绝对路径(请更改成你自己的目录)
|
||||
export ALIYUNPAN_CONFIG_DIR=/Users/tickstep/Applications/adrive/config
|
||||
# aliyunpan程序所在的绝对路径(请更改成你自己的目录)
|
||||
export ALIYUNPAN_BIN=/Users/tickstep/Applications/adrive/aliyunpan
|
||||
|
||||
# 本地目录(请更改成你自己的目录)
|
||||
# (可选)配置目录的绝对路径
|
||||
export ALIYUNPAN_CONFIG_DIR="/Users/tickstep/Applications/adrive/config"
|
||||
|
||||
# aliyunpan程序所在的绝对路径
|
||||
export ALIYUNPAN_BIN="/Users/tickstep/Applications/adrive/aliyunpan"
|
||||
|
||||
# 本地目录
|
||||
LOCAL_DIR="/tickstep/Documents/我的文档"
|
||||
# 网盘目录(请更改成你自己的目录)
|
||||
|
||||
# 网盘目录
|
||||
PAN_DIR="/我的文档"
|
||||
|
||||
# 执行上传
|
||||
$ALIYUNPAN_BIN upload -exn "^\." -exn "^@eadir$" "$LOCAL_DIR" $PAN_DIR"
|
||||
# 检查本地目录是否存在
|
||||
if [ ! -d "$LOCAL_DIR" ]; then
|
||||
echo "[ERROR] 本地目录不存在: $LOCAL_DIR"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 执行上传(已修复引号、添加安全引用和覆盖策略)
|
||||
"$ALIYUNPAN_BIN" upload \
|
||||
-exn "^\." \
|
||||
-exn "^@eadir$" \
|
||||
-ow \
|
||||
"$LOCAL_DIR" \
|
||||
"$PAN_DIR"
|
||||
|
||||
echo "[INFO] 上传任务执行完毕"
|
||||
```
|
||||
|
||||
增加脚本执行权限
|
||||
@@ -774,4 +790,4 @@ Windows
|
||||
|
||||
### 第二步
|
||||
打开aliyunpan命令行程序,任何云盘命令都有类似如下日志输出
|
||||

|
||||

|
||||
|
||||
@@ -15,8 +15,6 @@ package downloader
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"github.com/tickstep/library-go/logger"
|
||||
"github.com/tickstep/library-go/requester"
|
||||
mathrand "math/rand"
|
||||
"mime"
|
||||
"net/url"
|
||||
@@ -24,6 +22,10 @@ import (
|
||||
"regexp"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/tickstep/aliyunpan/internal/utils"
|
||||
"github.com/tickstep/library-go/logger"
|
||||
"github.com/tickstep/library-go/requester"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -102,15 +104,15 @@ func fixCacheSize(size *int) {
|
||||
|
||||
// IsUrlExpired 下载链接是否已过期。过期返回True
|
||||
func IsUrlExpired(urlStr string) bool {
|
||||
u, err := url.Parse(urlStr)
|
||||
expiredTimeSec, err := utils.GetExpiredTimeSecFromOSSUrl(urlStr)
|
||||
if err != nil {
|
||||
// 解析错误,默认过期
|
||||
return true
|
||||
}
|
||||
expiredTimeSecStr := u.Query().Get("x-oss-expires")
|
||||
expiredTimeSec, _ := strconv.ParseInt(expiredTimeSecStr, 10, 64)
|
||||
if (expiredTimeSec - time.Now().Unix()) <= 5 { // 小于5秒钟
|
||||
// expired
|
||||
return true
|
||||
}
|
||||
// 返回未过期
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -16,15 +16,15 @@ package panupload
|
||||
import (
|
||||
"crypto/sha1"
|
||||
"encoding/hex"
|
||||
"github.com/tickstep/aliyunpan/internal/config"
|
||||
"github.com/tickstep/library-go/converter"
|
||||
"github.com/tickstep/library-go/logger"
|
||||
"net/url"
|
||||
"os"
|
||||
"path"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/tickstep/aliyunpan/internal/config"
|
||||
"github.com/tickstep/aliyunpan/internal/utils"
|
||||
"github.com/tickstep/library-go/converter"
|
||||
"github.com/tickstep/library-go/logger"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -55,16 +55,16 @@ func getBlockSize(fileSize int64) int64 {
|
||||
|
||||
// IsUrlExpired 上传链接是否已过期。过期返回True
|
||||
func IsUrlExpired(urlStr string) bool {
|
||||
u, err := url.Parse(urlStr)
|
||||
expiredTimeSec, err := utils.GetExpiredTimeSecFromOSSUrl(urlStr)
|
||||
if err != nil {
|
||||
// 解析错误,默认过期
|
||||
return true
|
||||
}
|
||||
expiredTimeSecStr := u.Query().Get("x-oss-expires")
|
||||
expiredTimeSec, _ := strconv.ParseInt(expiredTimeSecStr, 10, 64)
|
||||
if (expiredTimeSec - time.Now().Unix()) <= 300 { // 小于5分钟
|
||||
// expired
|
||||
return true
|
||||
}
|
||||
// 返回未过期
|
||||
return false
|
||||
}
|
||||
|
||||
|
||||
@@ -383,3 +383,64 @@ func GetPublicIP() (string, error) {
|
||||
ip := strings.TrimSpace(strings.Split(ipResp.Origin, ",")[0])
|
||||
return ip, nil
|
||||
}
|
||||
|
||||
// GetExpiredTimeSecFromOSSUrl 从OSS URL中解析出统一的过期时间戳(秒)
|
||||
func GetExpiredTimeSecFromOSSUrl(rawURL string) (int64, error) {
|
||||
parsedURL, err := url.Parse(rawURL)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("failed to parse URL: %w", err)
|
||||
}
|
||||
|
||||
query := parsedURL.Query()
|
||||
sigVersion := query.Get("x-oss-signature-version")
|
||||
|
||||
var expires int64 = 0
|
||||
|
||||
// 检测版本标识(不区分大小写)
|
||||
if strings.Contains(sigVersion, "OSS4") {
|
||||
// V4 签名:x-oss-expires 为相对秒数,需要结合 x-oss-date
|
||||
expiresStr := query.Get("x-oss-expires")
|
||||
if expiresStr == "" {
|
||||
return 0, fmt.Errorf("V4 signature: 'x-oss-expires' parameter not found")
|
||||
}
|
||||
relSec, err := strconv.ParseInt(expiresStr, 10, 64)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("V4 signature: invalid 'x-oss-expires' value: %w", err)
|
||||
}
|
||||
|
||||
dateStr := query.Get("x-oss-date")
|
||||
if dateStr == "" {
|
||||
return 0, fmt.Errorf("V4 signature: 'x-oss-date' parameter not found")
|
||||
}
|
||||
// 解析 ISO8601 UTC 时间,例如 "20231220T083018Z"
|
||||
t, err := time.Parse("20060102T150405Z", dateStr)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("V4 signature: failed to parse 'x-oss-date': %w", err)
|
||||
}
|
||||
expires = t.Unix() + relSec
|
||||
|
||||
} else if strings.Contains(sigVersion, "OSS3") || strings.Contains(sigVersion, "OSS2") {
|
||||
// V2 / V3:x-oss-expires 为绝对时间戳
|
||||
expiresStr := query.Get("x-oss-expires")
|
||||
if expiresStr == "" {
|
||||
return 0, fmt.Errorf("V2/V3 signature: 'x-oss-expires' parameter not found")
|
||||
}
|
||||
expires, err = strconv.ParseInt(expiresStr, 10, 64)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("V2/V3 signature: invalid 'x-oss-expires' value: %w", err)
|
||||
}
|
||||
|
||||
} else {
|
||||
// 默认为 V1 签名(没有 x-oss-signature-version 或为空)
|
||||
expiresStr := query.Get("Expires")
|
||||
if expiresStr == "" {
|
||||
return 0, fmt.Errorf("V1 signature: 'Expires' parameter not found")
|
||||
}
|
||||
expires, err = strconv.ParseInt(expiresStr, 10, 64)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("V1 signature: invalid 'Expires' value: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
return expires, nil
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@ const (
|
||||
|
||||
var (
|
||||
// Version 版本号
|
||||
Version = "v0.3.9"
|
||||
Version = "v0.4.0"
|
||||
|
||||
// 命令历史文件
|
||||
historyFilePath = filepath.Join(config.GetConfigDir(), "aliyunpan_command_history.txt")
|
||||
|
||||
Binary file not shown.
Binary file not shown.
+6
-6
@@ -2,14 +2,14 @@
|
||||
"FixedFileInfo": {
|
||||
"FileVersion": {
|
||||
"Major": 0,
|
||||
"Minor": 3,
|
||||
"Patch": 9,
|
||||
"Minor": 4,
|
||||
"Patch": 0,
|
||||
"Build": 0
|
||||
},
|
||||
"ProductVersion": {
|
||||
"Major": 0,
|
||||
"Minor": 3,
|
||||
"Patch": 9,
|
||||
"Minor": 4,
|
||||
"Patch": 0,
|
||||
"Build": 0
|
||||
},
|
||||
"FileFlagsMask": "3f",
|
||||
@@ -22,14 +22,14 @@
|
||||
"Comments": "",
|
||||
"CompanyName": "tickstep",
|
||||
"FileDescription": "阿里云盘客户端",
|
||||
"FileVersion": "v0.3.9",
|
||||
"FileVersion": "v0.4.0",
|
||||
"InternalName": "",
|
||||
"LegalCopyright": "© 2021-2026 tickstep.",
|
||||
"LegalTrademarks": "",
|
||||
"OriginalFilename": "",
|
||||
"PrivateBuild": "",
|
||||
"ProductName": "aliyunpan",
|
||||
"ProductVersion": "v0.3.9",
|
||||
"ProductVersion": "v0.4.0",
|
||||
"SpecialBuild": ""
|
||||
},
|
||||
"VarFileInfo": {
|
||||
|
||||
Reference in New Issue
Block a user