github.com/qjfoidnh/BaiduPCS-Go@v0.0.0-20231011165705-caa18a3765f3/baidupcs/download.go (about)

     1  package baidupcs
     2  
     3  import (
     4  	"errors"
     5  	"github.com/qjfoidnh/BaiduPCS-Go/baidupcs/pcserror"
     6  	"github.com/qjfoidnh/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  	// InitRangeSize 初次请求的片段值
    15  	InitRangeSize = 32 * converter.KB
    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  }