提交 54e8fcc0 编写于 作者: P peterq

add: 网盘文件通过第三方vip加速下载

上级 a5c63129
......@@ -253,7 +253,7 @@ func (task *Task) capture(force bool) {
}
task.lastCaptureTime = time.Now()
c := &internal.TaskCapture{
Fid: string(task.fileId),
Fid: task.fileId,
SavePath: task.savePath,
Completed: []*internal.FinishSeg{},
Length: task.fileLength,
......
......@@ -13,11 +13,7 @@ func init() {
var downloadSyncRoutes = map[string]syncHandler{
"download.new": func(p map[string]interface{}) interface{} {
useVip := false
if u, ok := p["useVip"]; ok {
useVip = u.(bool)
}
taskId, err := pan_download.DownloadFile(p["fid"].(string), p["savePath"].(string), useVip)
taskId, err := pan_download.DownloadFile(p["fid"].(string), p["savePath"].(string))
if err != nil {
return err
}
......
......@@ -50,7 +50,7 @@ var panApiAsyncRoutes = map[string]asyncHandler{
}
},
"pan.rapid.md5": func(p map[string]interface{}, resolve func(interface{}), reject func(interface{}), progress func(interface{}), qmlMsg chan interface{}) {
sliceMd5, err := pan_download.RapidUploadMd5(fmt.Sprint(int(p["fid"].(float64))))
_, sliceMd5, _, err := pan_download.RapidUploadMd5(fmt.Sprint(int(p["fid"].(float64))))
if err != nil {
reject(err)
return
......
......@@ -88,7 +88,6 @@ Item {
var res = Util.callGoSync('download.resume', {
"downloadId": downloadId,
"bin": resumeData,
"useVip": meta.useVip
})
} else {
isNewAdd = false
......
......@@ -56,15 +56,16 @@ Item {
}).then(function (savePath) {
savePath = savePath.toString()
savePath = savePath.replace('file://', '')
var newFid = (useVip ? 'vip' : 'direct') + '.' + meta.fs_id
var id = Util.callGoSync('download.new', {
"fid": meta.fs_id + '',
"fid": newFid,
"savePath": savePath,
"useVip": !!useVip
})
var obj = JSON.parse(JSON.stringify(meta))
obj.downloadId = id
var sep = Qt.platform.os == "windows" ? '\\' : '/'
var t = String.prototype.split.call(savePath, sep)
obj.newFid = newFid
obj.saveName = t.pop()
obj.savePath = savePath
obj.useVip = !!useVip
......
......@@ -6,6 +6,7 @@ import (
"github.com/peterq/pan-light/pc/dep"
"github.com/peterq/pan-light/pc/downloader"
"github.com/peterq/pan-light/pc/pan-api"
"github.com/peterq/pan-light/pc/server-api"
"github.com/peterq/pan-light/pc/util"
"github.com/pkg/errors"
"io/ioutil"
......@@ -13,13 +14,13 @@ import (
"net/http"
"os"
"path/filepath"
"strconv"
"strings"
"time"
)
var manager *downloader.Manager
var useVipMap = map[downloader.TaskId]bool{}
func init() {
dep.OnInit(func() {
parallel := 1024
......@@ -27,7 +28,7 @@ func init() {
CoroutineNumber: 32,
SegmentSize: 1024 * 1024 * 2,
WroteToDiskBufferSize: 1024 * 512,
LinkResolver: pan_api.Link,
LinkResolver: linkResolver,
HttpClient: &http.Client{
Transport: &http.Transport{
MaxIdleConns: parallel,
......@@ -49,6 +50,37 @@ func Manager() *downloader.Manager {
return manager
}
func linkResolver(fileId string) (link string, err error) {
log.Println(fileId)
defer func() {
if e := recover(); e != nil {
err = errors.New("链接解析严重错误: " + fmt.Sprint(e))
}
}()
args := strings.Split(fileId, ".")
switch args[0] {
case "vip":
return vipLink(args[1])
case "direct":
return pan_api.Link(args[1])
case "share":
fileSize, _ := strconv.ParseInt(args[3], 10, 64)
return VipLinkByMd5(args[1], args[2], fileSize)
default:
err = errors.New("unknown download method: " + args[0])
}
return
}
func vipLink(fileId string) (link string, err error) {
md5, sliceMd5, fileSize, err := RapidUploadMd5(fileId)
if err != nil {
err = errors.Wrap(err, "获取文件md5错误")
return
}
return VipLinkByMd5(md5, sliceMd5, fileSize)
}
func handleDownloadEvent(event *downloader.DownloadEvent) {
dep.NotifyQml("task.event", map[string]interface{}{
"type": event.Event,
......@@ -61,24 +93,21 @@ func test() {
//fileCompare()
//return
time.Sleep(3 * time.Second)
id, err := DownloadFile("730136432970379", "./yx.mp4", false)
id, err := DownloadFile("direct.730136432970379", "./yx.mp4")
//id, err := DownloadFile("835313540804", "./project.mp4")
log.Println(id, err)
}
func DownloadFile(fid, savePath string, useVip bool) (taskId downloader.TaskId, err error) {
func DownloadFile(fid, savePath string) (taskId downloader.TaskId, err error) {
savePath, err = filepath.Abs(savePath)
if err != nil {
return
}
taskId, err = manager.NewTask(fid, savePath, requestDecorator)
if err == nil {
useVipMap[taskId] = true
}
return
}
func RapidUploadMd5(fid string) (sliceMd5 string, err error) {
func RapidUploadMd5(fid string) (md5, sliceMd5 string, fileSize int64, err error) {
link, err := pan_api.Link(fid)
if err != nil {
err = errors.Wrap(err, "解析直链错误")
......@@ -96,6 +125,15 @@ func RapidUploadMd5(fid string) (sliceMd5 string, err error) {
err = errors.Wrap(err, "访问直链错误")
return
}
md5 = resp.Header.Get("Content-Md5")
s := resp.Header.Get("Content-Range")
s = strings.Trim(s, "]")
s = strings.Split(s, "/")[1]
fileSize, err = strconv.ParseInt(s, 10, 64)
if err != nil {
err = errors.Wrap(err, "获取文件大小失败")
return
}
defer resp.Body.Close()
bin, err := ioutil.ReadAll(resp.Body)
if err != nil {
......@@ -109,15 +147,26 @@ func RapidUploadMd5(fid string) (sliceMd5 string, err error) {
return
}
func VipLinkByMd5(md5, sliceMd5 string, fileSize int64) (link string, err error) {
result, err := server_api.Call("link-md5", map[string]interface{}{
"md5": md5,
"sliceMd5": sliceMd5,
"fileSize": fileSize,
})
if err != nil {
err = errors.Wrap(err, "调用vip链接接口错误")
return
}
link = result.(string)
return
}
func requestDecorator(request *http.Request) *http.Request {
request.Header.Set("User-Agent", pan_api.BaiduUA)
return request
}
func Resume(id string, bin string, useVip bool) error {
if useVip {
useVipMap[downloader.TaskId(id)] = true
}
return manager.Resume(map[downloader.TaskId]string{
downloader.TaskId(id): bin,
}, requestDecorator)
......
......@@ -21,6 +21,7 @@ var urlMap = map[string]string{
"refresh-token": "/api/pc/refresh-token",
"share": "/api/pc/share",
"share-list": "/api/pc/share/list",
"link-md5": "/api/pc/link/md5",
}
var httpClient = http.Client{
//Timeout: 15 * time.Second,
......
......@@ -20,7 +20,7 @@ type VipSaveFileModel struct {
}
func (f *VipSaveFileModel) GetSavePath() string {
return "/pan-light-save/" + f.Md5[:2] + "/" + f.Md5[2:4]
return "/pan-light-save/" + f.Md5[:2] + "/" + f.Md5[2:4] + "/" + f.Md5
}
type vipSaveFileDao struct{}
......
......@@ -249,11 +249,49 @@ func (v *Vip) SaveFileByMd5(md5, sliceMd5, path string, contentLength int64) (fi
fileSize = int64(info["size"].(float64))
serverPath := info["path"].(string)
if serverPath[len(serverPath)-1] == ')' {
go v.DeleteFile(serverPath)
go v.DeleteFile(path)
}
return
}
func (v *Vip) LinkByFid(fid string) (link string, err error) {
log.Println(fid)
ss := v.loginSession()
data, err := v.request("GET", "https://pan.baidu.com/api/download", gson{
"sign": ss.Sign,
"timestamp": ss.Timestamp,
"fidlist": "[" + fid + "]",
"type": "dlink",
"channel": "chunlei",
"web": 1,
"app_id": "250528",
"bdstoken": ss.Bdstoken,
"logid": time.Now().UnixNano(),
"clienttype": 0,
}, nil)
if err != nil {
err = errors.Wrap(err, "")
return
}
log.Println(data)
link = data["dlink"].([]interface{})[0].(map[string]interface{})["dlink"].(string)
link = v.getRedirectedLink(link)
return
}
func (v *Vip) getRedirectedLink(link string) string {
req := newRequest("GET", link)
resp, err := v.http.Do(req)
if err != nil {
log.Println(err)
}
end := resp.Request.URL.String()
log.Println(end)
resp.Body.Close()
return end
}
func (v *Vip) inputSharePwd(link, secret string) (err error) {
t := strings.Split(link, "/")
......
......@@ -4,12 +4,13 @@ import (
"fmt"
"github.com/dgrijalva/jwt-go"
"github.com/kataras/iris/context"
"github.com/kataras/iris/core/errors"
"github.com/peterq/pan-light/server/artisan"
"github.com/peterq/pan-light/server/artisan/cache"
"github.com/peterq/pan-light/server/conf"
"github.com/peterq/pan-light/server/dao"
"github.com/peterq/pan-light/server/pan-viper"
"github.com/peterq/pan-light/server/pc-api/middleware"
"github.com/pkg/errors"
"gopkg.in/mgo.v2"
"strings"
"time"
......@@ -101,15 +102,9 @@ func handleFeedBack(ctx context.Context, param artisan.JsonMap) (result interfac
return
}
func handleShareToSquare(ctx context.Context, param artisan.JsonMap) (result interface{}, err error) {
md5 := param.Get("md5").String()
sliceMd5 := param.Get("sliceMd5").String()
title := param.Get("title").String()
duration := param.Get("duration").Int()
fileSize := param.Get("fileSize").Int64()
func getOrSaveByFile(md5, sliceMd5 string, fileSize int64) (data dao.VipSaveFileModel, err error) {
// 查找该文件是否被vip账号存储过
data, err := dao.VipSaveFileDao.GetByMd5(md5)
data, err = dao.VipSaveFileDao.GetByMd5(md5)
if err != nil && err != mgo.ErrNotFound {
err = artisan.NewError("database error", -1, err)
return
......@@ -145,6 +140,20 @@ func handleShareToSquare(ctx context.Context, param artisan.JsonMap) (result int
return
}
}
return
}
func handleShareToSquare(ctx context.Context, param artisan.JsonMap) (result interface{}, err error) {
md5 := param.Get("md5").String()
sliceMd5 := param.Get("sliceMd5").String()
title := param.Get("title").String()
duration := param.Get("duration").Int()
fileSize := param.Get("fileSize").Int64()
data, err := getOrSaveByFile(md5, sliceMd5, fileSize)
if err != nil {
return
}
// 写入分享表
share := dao.FileShareModel{
Uk: middleware.ContextLoginInfo(ctx).Uk(),
......@@ -187,3 +196,34 @@ func handleShareList(ctx context.Context, param artisan.JsonMap) (result interfa
}
return
}
func handleLinkMd5(ctx context.Context, param artisan.JsonMap) (result interface{}, err error) {
md5 := param.Get("md5").String()
sliceMd5 := param.Get("sliceMd5").String()
fileSize := param.Get("fileSize").Int64()
cacheKey := "cache-vip-link-" + md5
err = cache.RedisGet(cacheKey, &result)
if err == nil {
return
}
data, err := getOrSaveByFile(md5, sliceMd5, fileSize)
if err != nil {
return
}
vip := pan_viper.GetVipByUsername(data.Username)
if vip == nil {
err = errors.New("获取vip账户失败")
return
}
link, err := vip.LinkByFid(data.Fid)
if err != nil {
err = errors.Wrap(err, "获取vip链接错误")
return
}
result = link
cache.RedisSet(cacheKey, link, time.Hour)
return
}
......@@ -58,4 +58,9 @@ func pcAuthRoutes(r router.Party) {
Duration: time.Second * 5,
Number: 5,
}, handleShareList)
post("link/md5", artisan.ThrottleOption{
Duration: time.Second * 5,
Number: 5,
}, handleLinkMd5)
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册