diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6cbf4a8..5a67096 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,10 @@
# 189Cloud-Downloader
一个189云盘的下载器。(支持分享链接下载、支持Windows、Linux、macOS)Based Go.
+## v0.1.4
+1. 修复单文件分享时找不到shareId的问题。
+2. 修复在个别情况下载文件损坏的问题。
+
## v0.1.3
1. fix `get` current not found.
diff --git a/action.go b/action.go
index 2976e0e..087cb5f 100644
--- a/action.go
+++ b/action.go
@@ -92,6 +92,10 @@ func shareAction(ctx *cli.Context) (err error) {
return
}
share.AccessCode = strings.TrimSpace(ctx.Args().Get(1))
+ if share.IsFile {
+ paths = []*model.Path{{FileName: "share"}}
+ return
+ }
if _, paths, err = d.GetShareDirList(ctx.Context, share, 0, 0, ""); err != nil {
log.Error("d.GetShareDirList(%s) error(%v)", ctx.Args().Get(0), err)
return
@@ -118,9 +122,18 @@ func lsAction(ctx *cli.Context) (err error) {
return
}
} else if share != nil {
- if dirs, _, err = d.GetShareDirList(ctx.Context, share, pn, ps, order, path); err != nil {
- log.Error("d.GetShareDirList() pn(%d) ps(%d) fileId(%s) error(%v)", pn, ps, path, err)
- return
+ if !share.IsFile {
+ if dirs, _, err = d.GetShareDirList(ctx.Context, share, pn, ps, order, path); err != nil {
+ log.Error("d.GetShareDirList() pn(%d) ps(%d) fileId(%s) error(%v)", pn, ps, path, err)
+ return
+ }
+ } else {
+ var dir *model.Dir
+ if dir, err = d.GetShareFileInfo(ctx.Context, share); err != nil {
+ log.Error("d.GetShareFileInfo(%s) error(%v)", share.ShortCode, err)
+ return
+ }
+ dirs = []*model.Dir{dir}
}
} else {
if path != "" {
diff --git a/dao/get.go b/dao/get.go
index c420dec..8204280 100644
--- a/dao/get.go
+++ b/dao/get.go
@@ -74,10 +74,6 @@ func (d *dao) Download(ctx context.Context, url, toPath string, c int, tmpDirs .
} else {
shortName = string(r[:12]) + "..."
}
- if !strings.Contains(url, "https://cloud.189.cn") &&
- resp.Header.Get("Accept-Ranges") != "bytes" {
- c = 1
- }
if c != 1 && b < 10*1024*1024 {
c = 1
}
@@ -111,10 +107,12 @@ func (d *dao) Download(ctx context.Context, url, toPath string, c int, tmpDirs .
)
download:
if retry++; retry >= 3 {
- log.Error("file(%s) part(%d) 下载失败! 发生了如下错误:%v", matchs[1], i, err)
+ println()
+ log.Error("file(%s) part(%d) 下载失败!可能当前资源并不支持多线程下载!", matchs[1], i)
return
} else if retry > 0 {
- log.Info("file(%s) part(%d) 下载失败!正在进行重试...(%d/3)", matchs[1], i, retry)
+ println()
+ log.Error("file(%s) part(%d) 下载失败!正在进行重试...(%d/3)", matchs[1], i, retry)
bar.Add(-size)
size = 0
time.Sleep(3 * time.Second)
@@ -136,10 +134,11 @@ func (d *dao) Download(ctx context.Context, url, toPath string, c int, tmpDirs .
downResp.Body.Close()
goto download
}
- if _, err = d.readTo(tmpFile, downResp.Body, bar); err != nil {
+ time.Sleep(time.Duration(i) * time.Second)
+ var written int64
+ if written, err = d.readTo(tmpFile, downResp.Body, bar); err != nil || written < end-start {
downResp.Body.Close()
tmpFile.Close()
- log.Error("d.readTo(target, part) error(%v)", err)
goto download
}
return
@@ -194,8 +193,8 @@ func (d *dao) readTo(dst io.Writer, src io.Reader, bar ...*progressbar.Bar) (wri
}
}
if readErr != nil {
- if readErr != io.EOF &&
- readErr != io.ErrUnexpectedEOF {
+ if readErr != io.EOF && readErr != io.ErrUnexpectedEOF {
+ log.Error("d.readTo(target, part) error(%v)", readErr)
err = readErr
break
}
diff --git a/dao/share.go b/dao/share.go
index 4c0fdd3..0bc75d1 100644
--- a/dao/share.go
+++ b/dao/share.go
@@ -18,12 +18,14 @@ import (
)
const (
- _listShareDirAPI = "https://cloud.189.cn/v2/listShareDirByShareIdAndFileId.action?"
- _getDownloadUrlAPI = "https://cloud.189.cn/v2/getFileDownloadUrl.action?"
+ _listShareDirAPI = "https://cloud.189.cn/v2/listShareDirByShareIdAndFileId.action?"
+ _getShareFileInfoAPI = "https://cloud.189.cn/shareFileByVerifyCode.action?"
+ _getDownloadUrlAPI = "https://cloud.189.cn/v2/getFileDownloadUrl.action?"
)
var (
_shareIdReg = regexp.MustCompile(`var\s+_shareId\s+?=\s+?'(\d+)';`)
+ _shareIdReg2 = regexp.MustCompile(``)
_verifyCodeReg = regexp.MustCompile(`var\s+_verifyCode\s+?=\s+?'(\d+)';`)
_shortCodeReg = regexp.MustCompile(`https://cloud.189.cn/t/((?:\w+){12})`)
_shareNameReg = regexp.MustCompile(`
\s+(.*?)\s+`)
@@ -35,6 +37,7 @@ func (d *dao) GetShareInfo(ctx context.Context, url string) (share *model.ShareI
if resp, err = d.httpCli.Get(url); err != nil {
return
}
+ defer resp.Body.Close()
var body []byte
if body, err = ioutil.ReadAll(resp.Body); err != nil {
return
@@ -47,21 +50,27 @@ func (d *dao) GetShareInfo(ctx context.Context, url string) (share *model.ShareI
share.ShortCode = matchShortCode[1]
var matchShareID []string
if matchShareID = _shareIdReg.FindStringSubmatch(string(body)); len(matchShareID) <= 1 {
- err = errors.New("没能找到shareId,需要作者更新脚本。。。")
- return
+ if matchShareID = _shareIdReg2.FindStringSubmatch(string(body)); len(matchShareID) <= 1 {
+ err = errors.New("没能找到shareId,需要作者更新脚本。。。")
+ return
+ }
+ share.Name = "share"
+ share.IsFile = true
}
share.ShareID = matchShareID[1]
- var matchVerifyCode []string
- if matchVerifyCode = _verifyCodeReg.FindStringSubmatch(string(body)); len(matchVerifyCode) <= 1 {
- err = errors.New("没能找到verifyCode,需要作者更新脚本。。。")
- return
- }
- share.VerifyCode = matchVerifyCode[1]
- var matchShareName []string
- if matchShareName = _shareNameReg.FindStringSubmatch(string(body)); len(matchShareName) <= 1 {
- return
+ if !share.IsFile {
+ var matchVerifyCode []string
+ if matchVerifyCode = _verifyCodeReg.FindStringSubmatch(string(body)); len(matchVerifyCode) <= 1 {
+ err = errors.New("没能找到verifyCode,需要作者更新脚本。。。")
+ return
+ }
+ share.VerifyCode = matchVerifyCode[1]
+ var matchShareName []string
+ if matchShareName = _shareNameReg.FindStringSubmatch(string(body)); len(matchShareName) <= 1 {
+ return
+ }
+ share.Name = strings.Split(matchShareName[1], " ")[0]
}
- share.Name = strings.Split(matchShareName[1], " ")[0]
return
}
@@ -88,6 +97,7 @@ func (d *dao) GetShareDirList(ctx context.Context, share *model.ShareInfo, pn, p
log.Error("httpCli.Get(%s) 请求失败!error(%v)", _listShareDirAPI, err)
return
}
+ defer resp.Body.Close()
var body []byte
if body, err = ioutil.ReadAll(resp.Body); err != nil {
log.Error("ioutil.ReadAll error(%v)", err)
@@ -124,13 +134,56 @@ func (d *dao) GetShareDirAll(ctx context.Context, share *model.ShareInfo, fileID
}
}
+func (d *dao) GetShareFileInfo(ctx context.Context, share *model.ShareInfo) (info *model.Dir, err error) {
+ var params = url.Values{}
+ params.Set("accessCode", share.AccessCode)
+ params.Set("shortCode", share.ShortCode)
+ params.Set("noCache", utils.GenNoCacheNum())
+ var resp *http.Response
+ if resp, err = d.httpCli.Get(_getShareFileInfoAPI + params.Encode()); err != nil {
+ log.Error("httpCli.Get(%s) 请求失败!error(%v)", _getShareFileInfoAPI, err)
+ return
+ }
+ defer resp.Body.Close()
+ var body []byte
+ if body, err = ioutil.ReadAll(resp.Body); err != nil {
+ log.Error("ioutil.ReadAll error(%v)", err)
+ return
+ }
+ var res struct {
+ *model.Dir
+ ErrorVO *struct {
+ ErrorCode string `json:"errorCode"`
+ ErrorMsg string `json:"errorMsg"`
+ } `json:"errorVO"`
+ }
+ if err = json.Unmarshal(body, &res); err != nil {
+ log.Error("json.Unmarshal() error(%v)", err)
+ return
+ }
+ if res.ErrorVO != nil {
+ err = errors.New(res.ErrorVO.ErrorMsg)
+ return
+ }
+ if res.Dir == nil {
+ err = errors.New("请求失败!可能是访问码不正确。")
+ return
+ }
+ info = res.Dir
+ return
+}
+
func (d *dao) GetDownloadURLFromShare(ctx context.Context, share *model.ShareInfo, fileId, subFileId string) (URL string, err error) {
var params = url.Values{}
params.Set("shortCode", share.ShortCode)
- params.Set("fileId", fileId)
- params.Set("subFileId", subFileId)
params.Set("noCache", utils.GenNoCacheNum())
- params.Set("accessCode", share.AccessCode)
+ if !share.IsFile {
+ params.Set("fileId", fileId)
+ params.Set("subFileId", subFileId)
+ params.Set("accessCode", share.AccessCode)
+ } else {
+ params.Set("fileId", subFileId)
+ }
var req *http.Request
if req, err = http.NewRequest("GET", _getDownloadUrlAPI+params.Encode(), nil); err != nil {
log.Error("http.NewRequest(GET %s) error(%v)", _getDownloadUrlAPI, err)
diff --git a/model/share.go b/model/share.go
index 406f3a9..29e680d 100644
--- a/model/share.go
+++ b/model/share.go
@@ -6,6 +6,7 @@ type ShareInfo struct {
ShareID string
VerifyCode string
Name string
+ IsFile bool
}
func (share *ShareInfo) GetShortName() string {