github.com/fzfile/BaiduPCS-Go@v0.0.0-20200606205115-4408961cf336/baidupcs/download.go (about) 1 package baidupcs 2 3 import ( 4 "errors" 5 "github.com/fzfile/BaiduPCS-Go/baidupcs/pcserror" 6 "github.com/fzfile/BaiduPCS-Go/pcsutil/converter" 7 "net/http" 8 "net/url" 9 ) 10 11 var ( 12 // ErrLocateDownloadURLNotFound 未找到下载链接 13 ErrLocateDownloadURLNotFound = errors.New("locatedownload url not found") 14 // MaxDownloadRangeSize 文件片段最大值 15 MaxDownloadRangeSize = 55 * converter.MB 16 ) 17 18 type ( 19 // DownloadFunc 下载文件处理函数 20 DownloadFunc func(downloadURL string, jar http.CookieJar) error 21 22 // URLInfo 下载链接详情 23 URLInfo struct { 24 URLs []struct { 25 URL string `json:"url"` 26 } `json:"urls"` 27 } 28 29 // LocateDownloadInfoV1 locatedownload api v1 30 LocateDownloadInfoV1 struct { 31 Server []string `json:"server"` 32 PathJSON 33 } 34 35 locateDownloadJSON struct { 36 *pcserror.PCSErrInfo 37 URLInfo 38 } 39 40 // APIDownloadDlinkInfo 下载信息 41 APIDownloadDlinkInfo struct { 42 Dlink string `json:"dlink"` 43 FsID string `json:"fs_id"` 44 } 45 46 // APIDownloadDlinkInfoList 下载信息列表 47 APIDownloadDlinkInfoList []*APIDownloadDlinkInfo 48 49 panAPIDownloadJSON struct { 50 *pcserror.PanErrorInfo 51 DlinkList APIDownloadDlinkInfoList `json:"dlink"` 52 } 53 ) 54 55 // URLStrings 返回下载链接数组 56 func (ui *URLInfo) URLStrings(https bool) (urls []*url.URL) { 57 urls = make([]*url.URL, 0, len(ui.URLs)) 58 for k := range ui.URLs { 59 thisURL, err := url.Parse(ui.URLs[k].URL) 60 if err != nil { 61 continue 62 } 63 thisURL.Scheme = GetHTTPScheme(https) 64 urls = append(urls, thisURL) 65 } 66 return urls 67 } 68 69 // SingleURL 返回单条下载链接 70 func (ui *URLInfo) SingleURL(https bool) *url.URL { 71 if len(ui.URLs) < 1 { 72 return nil 73 } 74 75 u, err := url.Parse(ui.URLs[0].URL) 76 if err != nil { 77 return nil 78 } 79 u.Scheme = GetHTTPScheme(https) 80 return u 81 } 82 83 // LastURL 返回最后一条下载链接 84 func (ui *URLInfo) LastURL(https bool) *url.URL { 85 if len(ui.URLs) < 1 { 86 return nil 87 } 88 89 u, err := url.Parse(ui.URLs[len(ui.URLs)-1].URL) 90 if err != nil { 91 return nil 92 } 93 u.Scheme = GetHTTPScheme(https) 94 return u 95 } 96 97 // DownloadFile 下载单个文件 98 func (pcs *BaiduPCS) DownloadFile(path string, downloadFunc DownloadFunc) (err error) { 99 pcs.lazyInit() 100 pcsURL := pcs.generatePCSURL("file", "download", map[string]string{ 101 "path": path, 102 }) 103 baiduPCSVerbose.Infof("%s URL: %s\n", OperationDownloadFile, pcsURL) 104 105 return downloadFunc(pcsURL.String(), pcs.client.Jar) 106 } 107 108 // DownloadStreamFile 下载流式文件 109 func (pcs *BaiduPCS) DownloadStreamFile(path string, downloadFunc DownloadFunc) (err error) { 110 pcs.lazyInit() 111 pcsURL := pcs.generatePCSURL("stream", "download", map[string]string{ 112 "path": path, 113 }) 114 baiduPCSVerbose.Infof("%s URL: %s\n", OperationDownloadStreamFile, pcsURL) 115 116 return downloadFunc(pcsURL.String(), pcs.client.Jar) 117 } 118 119 // LocateDownloadWithUserAgent 获取下载链接 120 func (pcs *BaiduPCS) LocateDownload(pcspath string) (info *URLInfo, pcsError pcserror.Error) { 121 dataReadCloser, pcsError := pcs.PrepareLocateDownload(pcspath) 122 if dataReadCloser != nil { 123 defer dataReadCloser.Close() 124 } 125 if pcsError != nil { 126 return nil, pcsError 127 } 128 129 errInfo := pcserror.NewPCSErrorInfo(OperationLocateDownload) 130 jsonData := locateDownloadJSON{ 131 PCSErrInfo: errInfo, 132 } 133 134 pcsError = pcserror.HandleJSONParse(OperationLocateDownload, dataReadCloser, &jsonData) 135 if pcsError != nil { 136 return 137 } 138 139 return &jsonData.URLInfo, nil 140 } 141 142 // LocatePanAPIDownload 从百度网盘首页获取下载链接 143 func (pcs *BaiduPCS) LocatePanAPIDownload(fidList ...int64) (dlinkInfoList APIDownloadDlinkInfoList, pcsError pcserror.Error) { 144 dataReadCloser, pcsError := pcs.PrepareLocatePanAPIDownload(fidList...) 145 if dataReadCloser != nil { 146 defer dataReadCloser.Close() 147 } 148 if pcsError != nil { 149 return nil, pcsError 150 } 151 152 jsonData := panAPIDownloadJSON{ 153 PanErrorInfo: pcserror.NewPanErrorInfo(OperationLocatePanAPIDownload), 154 } 155 pcsError = pcserror.HandleJSONParse(OperationLocatePanAPIDownload, dataReadCloser, &jsonData) 156 if pcsError != nil { 157 if pcsError.GetErrType() == pcserror.ErrTypeRemoteError { 158 switch pcsError.GetRemoteErrCode() { 159 case 112: // 页面已过期 160 fallthrough 161 case 113: // 签名错误 162 pcs.ph.SetSignExpires() // 重置 163 } 164 } 165 return 166 } 167 168 return jsonData.DlinkList, nil 169 }