Skip to content

Commit 54e8fcc

Browse files
committed
add: 网盘文件通过第三方vip加速下载
1 parent a5c6312 commit 54e8fcc

File tree

11 files changed

+162
-33
lines changed

11 files changed

+162
-33
lines changed

pc/downloader/task.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -253,7 +253,7 @@ func (task *Task) capture(force bool) {
253253
}
254254
task.lastCaptureTime = time.Now()
255255
c := &internal.TaskCapture{
256-
Fid: string(task.fileId),
256+
Fid: task.fileId,
257257
SavePath: task.savePath,
258258
Completed: []*internal.FinishSeg{},
259259
Length: task.fileLength,

pc/functions/download.go

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,7 @@ func init() {
1313

1414
var downloadSyncRoutes = map[string]syncHandler{
1515
"download.new": func(p map[string]interface{}) interface{} {
16-
useVip := false
17-
if u, ok := p["useVip"]; ok {
18-
useVip = u.(bool)
19-
}
20-
taskId, err := pan_download.DownloadFile(p["fid"].(string), p["savePath"].(string), useVip)
16+
taskId, err := pan_download.DownloadFile(p["fid"].(string), p["savePath"].(string))
2117
if err != nil {
2218
return err
2319
}

pc/functions/pan-api.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ var panApiAsyncRoutes = map[string]asyncHandler{
5050
}
5151
},
5252
"pan.rapid.md5": func(p map[string]interface{}, resolve func(interface{}), reject func(interface{}), progress func(interface{}), qmlMsg chan interface{}) {
53-
sliceMd5, err := pan_download.RapidUploadMd5(fmt.Sprint(int(p["fid"].(float64))))
53+
_, sliceMd5, _, err := pan_download.RapidUploadMd5(fmt.Sprint(int(p["fid"].(float64))))
5454
if err != nil {
5555
reject(err)
5656
return

pc/gui/qml/transfer/DownloadItem.qml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,6 @@ Item {
8888
var res = Util.callGoSync('download.resume', {
8989
"downloadId": downloadId,
9090
"bin": resumeData,
91-
"useVip": meta.useVip
9291
})
9392
} else {
9493
isNewAdd = false

pc/gui/qml/transfer/transfer.qml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,15 +56,16 @@ Item {
5656
}).then(function (savePath) {
5757
savePath = savePath.toString()
5858
savePath = savePath.replace('file://', '')
59+
var newFid = (useVip ? 'vip' : 'direct') + '.' + meta.fs_id
5960
var id = Util.callGoSync('download.new', {
60-
"fid": meta.fs_id + '',
61+
"fid": newFid,
6162
"savePath": savePath,
62-
"useVip": !!useVip
6363
})
6464
var obj = JSON.parse(JSON.stringify(meta))
6565
obj.downloadId = id
6666
var sep = Qt.platform.os == "windows" ? '\\' : '/'
6767
var t = String.prototype.split.call(savePath, sep)
68+
obj.newFid = newFid
6869
obj.saveName = t.pop()
6970
obj.savePath = savePath
7071
obj.useVip = !!useVip

pc/pan-download/pan-download.go

Lines changed: 61 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,28 +6,29 @@ import (
66
"github.com/peterq/pan-light/pc/dep"
77
"github.com/peterq/pan-light/pc/downloader"
88
"github.com/peterq/pan-light/pc/pan-api"
9+
"github.com/peterq/pan-light/pc/server-api"
910
"github.com/peterq/pan-light/pc/util"
1011
"github.com/pkg/errors"
1112
"io/ioutil"
1213
"log"
1314
"net/http"
1415
"os"
1516
"path/filepath"
17+
"strconv"
18+
"strings"
1619
"time"
1720
)
1821

1922
var manager *downloader.Manager
2023

21-
var useVipMap = map[downloader.TaskId]bool{}
22-
2324
func init() {
2425
dep.OnInit(func() {
2526
parallel := 1024
2627
manager = &downloader.Manager{
2728
CoroutineNumber: 32,
2829
SegmentSize: 1024 * 1024 * 2,
2930
WroteToDiskBufferSize: 1024 * 512,
30-
LinkResolver: pan_api.Link,
31+
LinkResolver: linkResolver,
3132
HttpClient: &http.Client{
3233
Transport: &http.Transport{
3334
MaxIdleConns: parallel,
@@ -49,6 +50,37 @@ func Manager() *downloader.Manager {
4950
return manager
5051
}
5152

53+
func linkResolver(fileId string) (link string, err error) {
54+
log.Println(fileId)
55+
defer func() {
56+
if e := recover(); e != nil {
57+
err = errors.New("链接解析严重错误: " + fmt.Sprint(e))
58+
}
59+
}()
60+
args := strings.Split(fileId, ".")
61+
switch args[0] {
62+
case "vip":
63+
return vipLink(args[1])
64+
case "direct":
65+
return pan_api.Link(args[1])
66+
case "share":
67+
fileSize, _ := strconv.ParseInt(args[3], 10, 64)
68+
return VipLinkByMd5(args[1], args[2], fileSize)
69+
default:
70+
err = errors.New("unknown download method: " + args[0])
71+
}
72+
return
73+
}
74+
75+
func vipLink(fileId string) (link string, err error) {
76+
md5, sliceMd5, fileSize, err := RapidUploadMd5(fileId)
77+
if err != nil {
78+
err = errors.Wrap(err, "获取文件md5错误")
79+
return
80+
}
81+
return VipLinkByMd5(md5, sliceMd5, fileSize)
82+
}
83+
5284
func handleDownloadEvent(event *downloader.DownloadEvent) {
5385
dep.NotifyQml("task.event", map[string]interface{}{
5486
"type": event.Event,
@@ -61,24 +93,21 @@ func test() {
6193
//fileCompare()
6294
//return
6395
time.Sleep(3 * time.Second)
64-
id, err := DownloadFile("730136432970379", "./yx.mp4", false)
96+
id, err := DownloadFile("direct.730136432970379", "./yx.mp4")
6597
//id, err := DownloadFile("835313540804", "./project.mp4")
6698
log.Println(id, err)
6799
}
68100

69-
func DownloadFile(fid, savePath string, useVip bool) (taskId downloader.TaskId, err error) {
101+
func DownloadFile(fid, savePath string) (taskId downloader.TaskId, err error) {
70102
savePath, err = filepath.Abs(savePath)
71103
if err != nil {
72104
return
73105
}
74106
taskId, err = manager.NewTask(fid, savePath, requestDecorator)
75-
if err == nil {
76-
useVipMap[taskId] = true
77-
}
78107
return
79108
}
80109

81-
func RapidUploadMd5(fid string) (sliceMd5 string, err error) {
110+
func RapidUploadMd5(fid string) (md5, sliceMd5 string, fileSize int64, err error) {
82111
link, err := pan_api.Link(fid)
83112
if err != nil {
84113
err = errors.Wrap(err, "解析直链错误")
@@ -96,6 +125,15 @@ func RapidUploadMd5(fid string) (sliceMd5 string, err error) {
96125
err = errors.Wrap(err, "访问直链错误")
97126
return
98127
}
128+
md5 = resp.Header.Get("Content-Md5")
129+
s := resp.Header.Get("Content-Range")
130+
s = strings.Trim(s, "]")
131+
s = strings.Split(s, "/")[1]
132+
fileSize, err = strconv.ParseInt(s, 10, 64)
133+
if err != nil {
134+
err = errors.Wrap(err, "获取文件大小失败")
135+
return
136+
}
99137
defer resp.Body.Close()
100138
bin, err := ioutil.ReadAll(resp.Body)
101139
if err != nil {
@@ -109,15 +147,26 @@ func RapidUploadMd5(fid string) (sliceMd5 string, err error) {
109147
return
110148
}
111149

150+
func VipLinkByMd5(md5, sliceMd5 string, fileSize int64) (link string, err error) {
151+
result, err := server_api.Call("link-md5", map[string]interface{}{
152+
"md5": md5,
153+
"sliceMd5": sliceMd5,
154+
"fileSize": fileSize,
155+
})
156+
if err != nil {
157+
err = errors.Wrap(err, "调用vip链接接口错误")
158+
return
159+
}
160+
link = result.(string)
161+
return
162+
}
163+
112164
func requestDecorator(request *http.Request) *http.Request {
113165
request.Header.Set("User-Agent", pan_api.BaiduUA)
114166
return request
115167
}
116168

117169
func Resume(id string, bin string, useVip bool) error {
118-
if useVip {
119-
useVipMap[downloader.TaskId(id)] = true
120-
}
121170
return manager.Resume(map[downloader.TaskId]string{
122171
downloader.TaskId(id): bin,
123172
}, requestDecorator)

pc/server-api/server-api.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ var urlMap = map[string]string{
2121
"refresh-token": "/api/pc/refresh-token",
2222
"share": "/api/pc/share",
2323
"share-list": "/api/pc/share/list",
24+
"link-md5": "/api/pc/link/md5",
2425
}
2526
var httpClient = http.Client{
2627
//Timeout: 15 * time.Second,

server/dao/vip-save-file.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ type VipSaveFileModel struct {
2020
}
2121

2222
func (f *VipSaveFileModel) GetSavePath() string {
23-
return "/pan-light-save/" + f.Md5[:2] + "/" + f.Md5[2:4]
23+
return "/pan-light-save/" + f.Md5[:2] + "/" + f.Md5[2:4] + "/" + f.Md5
2424
}
2525

2626
type vipSaveFileDao struct{}

server/pan-viper/vip.go

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -249,11 +249,49 @@ func (v *Vip) SaveFileByMd5(md5, sliceMd5, path string, contentLength int64) (fi
249249
fileSize = int64(info["size"].(float64))
250250
serverPath := info["path"].(string)
251251
if serverPath[len(serverPath)-1] == ')' {
252-
go v.DeleteFile(serverPath)
252+
go v.DeleteFile(path)
253253
}
254254
return
255255
}
256256

257+
func (v *Vip) LinkByFid(fid string) (link string, err error) {
258+
log.Println(fid)
259+
ss := v.loginSession()
260+
261+
data, err := v.request("GET", "https://pan.baidu.com/api/download", gson{
262+
"sign": ss.Sign,
263+
"timestamp": ss.Timestamp,
264+
"fidlist": "[" + fid + "]",
265+
"type": "dlink",
266+
"channel": "chunlei",
267+
"web": 1,
268+
"app_id": "250528",
269+
"bdstoken": ss.Bdstoken,
270+
"logid": time.Now().UnixNano(),
271+
"clienttype": 0,
272+
}, nil)
273+
if err != nil {
274+
err = errors.Wrap(err, "")
275+
return
276+
}
277+
log.Println(data)
278+
link = data["dlink"].([]interface{})[0].(map[string]interface{})["dlink"].(string)
279+
link = v.getRedirectedLink(link)
280+
return
281+
}
282+
283+
func (v *Vip) getRedirectedLink(link string) string {
284+
req := newRequest("GET", link)
285+
resp, err := v.http.Do(req)
286+
if err != nil {
287+
log.Println(err)
288+
}
289+
end := resp.Request.URL.String()
290+
log.Println(end)
291+
resp.Body.Close()
292+
return end
293+
}
294+
257295
func (v *Vip) inputSharePwd(link, secret string) (err error) {
258296

259297
t := strings.Split(link, "/")

server/pc-api/handlers.go

Lines changed: 49 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,13 @@ import (
44
"fmt"
55
"github.com/dgrijalva/jwt-go"
66
"github.com/kataras/iris/context"
7-
"github.com/kataras/iris/core/errors"
87
"github.com/peterq/pan-light/server/artisan"
8+
"github.com/peterq/pan-light/server/artisan/cache"
99
"github.com/peterq/pan-light/server/conf"
1010
"github.com/peterq/pan-light/server/dao"
1111
"github.com/peterq/pan-light/server/pan-viper"
1212
"github.com/peterq/pan-light/server/pc-api/middleware"
13+
"github.com/pkg/errors"
1314
"gopkg.in/mgo.v2"
1415
"strings"
1516
"time"
@@ -101,15 +102,9 @@ func handleFeedBack(ctx context.Context, param artisan.JsonMap) (result interfac
101102
return
102103
}
103104

104-
func handleShareToSquare(ctx context.Context, param artisan.JsonMap) (result interface{}, err error) {
105-
md5 := param.Get("md5").String()
106-
sliceMd5 := param.Get("sliceMd5").String()
107-
title := param.Get("title").String()
108-
duration := param.Get("duration").Int()
109-
fileSize := param.Get("fileSize").Int64()
110-
105+
func getOrSaveByFile(md5, sliceMd5 string, fileSize int64) (data dao.VipSaveFileModel, err error) {
111106
// 查找该文件是否被vip账号存储过
112-
data, err := dao.VipSaveFileDao.GetByMd5(md5)
107+
data, err = dao.VipSaveFileDao.GetByMd5(md5)
113108
if err != nil && err != mgo.ErrNotFound {
114109
err = artisan.NewError("database error", -1, err)
115110
return
@@ -145,6 +140,20 @@ func handleShareToSquare(ctx context.Context, param artisan.JsonMap) (result int
145140
return
146141
}
147142
}
143+
return
144+
}
145+
146+
func handleShareToSquare(ctx context.Context, param artisan.JsonMap) (result interface{}, err error) {
147+
md5 := param.Get("md5").String()
148+
sliceMd5 := param.Get("sliceMd5").String()
149+
title := param.Get("title").String()
150+
duration := param.Get("duration").Int()
151+
fileSize := param.Get("fileSize").Int64()
152+
153+
data, err := getOrSaveByFile(md5, sliceMd5, fileSize)
154+
if err != nil {
155+
return
156+
}
148157
// 写入分享表
149158
share := dao.FileShareModel{
150159
Uk: middleware.ContextLoginInfo(ctx).Uk(),
@@ -187,3 +196,34 @@ func handleShareList(ctx context.Context, param artisan.JsonMap) (result interfa
187196
}
188197
return
189198
}
199+
200+
func handleLinkMd5(ctx context.Context, param artisan.JsonMap) (result interface{}, err error) {
201+
md5 := param.Get("md5").String()
202+
sliceMd5 := param.Get("sliceMd5").String()
203+
fileSize := param.Get("fileSize").Int64()
204+
205+
cacheKey := "cache-vip-link-" + md5
206+
err = cache.RedisGet(cacheKey, &result)
207+
if err == nil {
208+
return
209+
}
210+
211+
data, err := getOrSaveByFile(md5, sliceMd5, fileSize)
212+
if err != nil {
213+
return
214+
}
215+
216+
vip := pan_viper.GetVipByUsername(data.Username)
217+
if vip == nil {
218+
err = errors.New("获取vip账户失败")
219+
return
220+
}
221+
link, err := vip.LinkByFid(data.Fid)
222+
if err != nil {
223+
err = errors.Wrap(err, "获取vip链接错误")
224+
return
225+
}
226+
result = link
227+
cache.RedisSet(cacheKey, link, time.Hour)
228+
return
229+
}

0 commit comments

Comments
 (0)