routine:
This commit is contained in:
commit
3287531ea5
|
@ -0,0 +1,28 @@
|
|||
.DS_Store
|
||||
node_modules
|
||||
/dist
|
||||
|
||||
|
||||
# local env files
|
||||
.env.local
|
||||
.env.*.local
|
||||
|
||||
# Log files
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
|
||||
# Editor directories and files
|
||||
.idea
|
||||
.vscode
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
||||
.env
|
||||
|
||||
**/.DS_Store
|
||||
|
||||
.DS_Store?
|
|
@ -0,0 +1,6 @@
|
|||
# 百度云盘上传api
|
||||
|
||||
- [api文档](https://pan.baidu.com/union/doc/3ksg0s9ye)
|
||||
- demo/upload_precreate.go 为如何使用 precreate 预上传接口的示例。
|
||||
- demo/upload_upload.go 为如何使用 upload 分片上传接口的示例。
|
||||
- demo/upload_create.go 为如何使用 create 创建文件接口的示例。
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,38 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"gitea.wolves.top/golang/BaiduDisk-util/upload"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
||||
// 使用示例
|
||||
|
||||
// 用户的access_token
|
||||
accessToken := "your-access-token"
|
||||
|
||||
// path与precreate的一致
|
||||
path := "/apps/hhhkoo/testfile.pdf"
|
||||
|
||||
// size与precreate的一致
|
||||
var size uint64
|
||||
size = 7141246
|
||||
|
||||
// blocklist与precreate的一致
|
||||
blockList := []string{}
|
||||
blockList = append(blockList, "18f2607ce63714753ef640be507fe8f4")
|
||||
blockList = append(blockList, "f4bea7d615c2429258f615397c7cd11c")
|
||||
|
||||
// uploadId为precreate返回的uploadId
|
||||
uploadId := "P1-MTAuMTQ0LjEyOC4xNToxNjUxMDI5MTE1OjM5NTM0NjY0MTQ4NjIxMzE0OA=="
|
||||
|
||||
// // call create API
|
||||
arg := upload.NewCreateArg(uploadId, path, size, blockList)
|
||||
if ret, err := upload.Create(accessToken, arg); err != nil {
|
||||
fmt.Printf("[msg: create this part error] [err:%v]", err.Error())
|
||||
} else {
|
||||
fmt.Printf("ret:%+v", ret)
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"gitea.wolves.top/golang/BaiduDisk-util/upload"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// 使用示例
|
||||
|
||||
// 用户的access_token
|
||||
accessToken := "your-access-token"
|
||||
|
||||
// 要保存到网盘的文件路径
|
||||
// 前缀必须为:/apps/您的应用名/
|
||||
path := "/apps/hhhkoo/testfile.pdf"
|
||||
|
||||
// 测试文件testfile.pdf的大小,单位:B
|
||||
var size uint64
|
||||
size = 7141246
|
||||
|
||||
// testfile.pdf 6.8MB,超出4MB。以4MB为单位切分,切分为两个:aa和ab。
|
||||
// 分片aa 的md5 为18f2607ce63714753ef640be507fe8f4
|
||||
// 分片ab 的md5 为f4bea7d615c2429258f615397c7cd11c
|
||||
// MD5是一种通用的加密算法
|
||||
// shell语言下,获取文件aa MD5的语法是: md5sum aa
|
||||
var blockList []string
|
||||
blockList = append(blockList, "18f2607ce63714753ef640be507fe8f4")
|
||||
blockList = append(blockList, "f4bea7d615c2429258f615397c7cd11c")
|
||||
|
||||
// call precreate API
|
||||
arg := upload.NewPrecreateArg(path, size, blockList)
|
||||
if ret, err := upload.Precreate(accessToken, arg); err != nil {
|
||||
fmt.Printf("[msg: precreate error] [err:%v]", err.Error())
|
||||
} else {
|
||||
fmt.Printf("ret:%+v", ret)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"gitea.wolves.top/golang/BaiduDisk-util/upload"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// 使用示例
|
||||
|
||||
// 用户的access_token
|
||||
accessToken := "your-access-token"
|
||||
|
||||
// uploadId为precreate返回的uploadId
|
||||
uploadId := "P1-MTAuMTQ0LjEyOC4xNToxNjUxMDI5MTE1OjM5NTM0NjY0MTQ4NjIxMzE0OA=="
|
||||
|
||||
// path与precreate的一致
|
||||
path := "/apps/hhhkoo/testfile.pdf"
|
||||
|
||||
// 上传第1个分片
|
||||
file := "第1个分片aa的本地文件路径"
|
||||
partseq := 0
|
||||
// call upload API
|
||||
arg := upload.NewUploadArg(uploadId, path, file, partseq)
|
||||
if ret, err := upload.Upload(accessToken, arg); err != nil {
|
||||
fmt.Printf("[msg: upload this part error] [err:%v]", err.Error())
|
||||
} else {
|
||||
fmt.Printf("ret:%+v", ret)
|
||||
}
|
||||
|
||||
// 上传第2个分片
|
||||
file = "第2个分片ab的本地文件路径"
|
||||
partseq = 1
|
||||
// call upload API
|
||||
arg = upload.NewUploadArg(uploadId, path, file, partseq)
|
||||
if ret, err := upload.Upload(accessToken, arg); err != nil {
|
||||
fmt.Printf("[msg: upload this part error] [err:%v]", err.Error())
|
||||
} else {
|
||||
fmt.Printf("ret:%+v", ret)
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
package upload
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"gitea.wolves.top/golang/BaiduDisk-util/utils"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// create
|
||||
//
|
||||
// RETURNS:
|
||||
// - CreateReturn: create return
|
||||
// - error: the return error if any occurs
|
||||
func Create(accessToken string, arg *CreateArg) (CreateReturn, error) {
|
||||
ret := CreateReturn{}
|
||||
|
||||
protocal := "https"
|
||||
host := "pan.baidu.com"
|
||||
router := "/rest/2.0/xpan/file?method=create&"
|
||||
uri := protocal + "://" + host + router
|
||||
|
||||
headers := map[string]string{
|
||||
"Host": host,
|
||||
"Content-Type": "application/x-www-form-urlencoded",
|
||||
}
|
||||
|
||||
params := url.Values{}
|
||||
params.Set("access_token", accessToken)
|
||||
uri += params.Encode()
|
||||
|
||||
postBody := url.Values{}
|
||||
postBody.Add("rtype", "2")
|
||||
postBody.Add("path", arg.Path)
|
||||
postBody.Add("size", strconv.FormatUint(arg.Size, 10))
|
||||
postBody.Add("isdir", "0")
|
||||
js, _ := json.Marshal(arg.BlockList)
|
||||
postBody.Add("block_list", string(js))
|
||||
postBody.Add("uploadid", arg.UploadId)
|
||||
|
||||
var body string
|
||||
var err error
|
||||
|
||||
body, _, err = utils.DoHTTPRequest(uri, strings.NewReader(postBody.Encode()), headers)
|
||||
if err != nil {
|
||||
return ret, err
|
||||
}
|
||||
if err = json.Unmarshal([]byte(body), &ret); err != nil {
|
||||
return ret, errors.New("unmarshal create body failed")
|
||||
}
|
||||
if ret.Errno != 0 {
|
||||
return ret, errors.New("call create failed")
|
||||
}
|
||||
return ret, nil
|
||||
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
package upload
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"gitea.wolves.top/golang/BaiduDisk-util/utils"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Precreate
|
||||
//
|
||||
// RETURNS:
|
||||
// - PrecreateReturn: precreate return
|
||||
// - error: the return error if any occurs
|
||||
func Precreate(accessToken string, arg *PrecreateArg) (PrecreateReturn, error) {
|
||||
ret := PrecreateReturn{}
|
||||
|
||||
protocal := "https"
|
||||
host := "pan.baidu.com"
|
||||
router := "/rest/2.0/xpan/file?method=precreate&"
|
||||
uri := protocal + "://" + host + router
|
||||
|
||||
params := url.Values{}
|
||||
params.Set("access_token", accessToken)
|
||||
uri += params.Encode()
|
||||
|
||||
headers := map[string]string{
|
||||
"Host": host,
|
||||
"Content-Type": "application/x-www-form-urlencoded",
|
||||
}
|
||||
|
||||
postBody := url.Values{}
|
||||
postBody.Add("path", arg.Path)
|
||||
postBody.Add("size", strconv.FormatUint(arg.Size, 10))
|
||||
blockListJson, _ := json.Marshal(arg.BlockList)
|
||||
postBody.Add("block_list", string(blockListJson))
|
||||
postBody.Add("isdir", "0")
|
||||
postBody.Add("autoinit", "1")
|
||||
// 当path冲突且block_list不同时,进行重命名
|
||||
postBody.Add("rtype", "2")
|
||||
|
||||
body, _, err := utils.DoHTTPRequest(uri, strings.NewReader(postBody.Encode()), headers)
|
||||
if err != nil {
|
||||
return ret, err
|
||||
}
|
||||
if err = json.Unmarshal([]byte(body), &ret); err != nil {
|
||||
return ret, errors.New("unmarshal precreate body failed,body")
|
||||
}
|
||||
if ret.Errno != 0 {
|
||||
return ret, errors.New("call precreate failed")
|
||||
}
|
||||
return ret, nil
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
package upload
|
||||
|
||||
// precreate 参数
|
||||
type PrecreateArg struct {
|
||||
Path string `json:"path"`
|
||||
Size uint64 `json:"size"`
|
||||
BlockList []string `json:"block_list"`
|
||||
}
|
||||
|
||||
// 创建 PrecreateArg 实例
|
||||
func NewPrecreateArg(path string, size uint64, blockList []string) *PrecreateArg {
|
||||
s := new(PrecreateArg)
|
||||
s.Path = path
|
||||
s.Size = size
|
||||
s.BlockList = blockList
|
||||
return s
|
||||
}
|
||||
|
||||
// PrecreateReturn
|
||||
type PrecreateReturn struct {
|
||||
Errno int `json:"errno"`
|
||||
ReturnType int `json:"return_type"`
|
||||
BlockList []int `json:"block_list"` // 分片序号列表
|
||||
UploadId string `json:"uploadid"`
|
||||
RequestId int `json:"request_id"`
|
||||
}
|
||||
|
||||
// upload 参数
|
||||
type UploadArg struct {
|
||||
UploadId string `json:"uploadid"`
|
||||
Path string `json:"path"`
|
||||
LocalFile string `json:"local_file"`
|
||||
Partseq int `json:"partseq"`
|
||||
}
|
||||
|
||||
// 创建 UploadArg 实例
|
||||
func NewUploadArg(uploadId string, path string, localFile string, partseq int) *UploadArg {
|
||||
s := new(UploadArg)
|
||||
s.UploadId = uploadId
|
||||
s.Path = path
|
||||
s.LocalFile = localFile
|
||||
s.Partseq = partseq
|
||||
return s
|
||||
}
|
||||
|
||||
// UploadReturn
|
||||
type UploadReturn struct {
|
||||
Md5 string `json:"md5"`
|
||||
RequestId int `json:"request_id"`
|
||||
}
|
||||
|
||||
// create 参数
|
||||
type CreateArg struct {
|
||||
UploadId string `json:"uploadid"`
|
||||
Path string `json:"path"`
|
||||
Size uint64 `json:"size"`
|
||||
BlockList []string `json:"block_list"`
|
||||
}
|
||||
|
||||
// 创建 CreateArg 实例
|
||||
func NewCreateArg(uploadId string, path string, size uint64, blockList []string) *CreateArg {
|
||||
s := new(CreateArg)
|
||||
s.UploadId = uploadId
|
||||
s.Path = path
|
||||
s.Size = size
|
||||
s.BlockList = blockList
|
||||
return s
|
||||
}
|
||||
|
||||
// CreateReturn
|
||||
type CreateReturn struct {
|
||||
Errno int `json:"errno"`
|
||||
Path string `json:"path"`
|
||||
}
|
|
@ -0,0 +1,86 @@
|
|||
package upload
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"gitea.wolves.top/golang/BaiduDisk-util/utils"
|
||||
"io"
|
||||
"mime/multipart"
|
||||
"net/url"
|
||||
"os"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
func Upload(accessToken string, arg *UploadArg) (UploadReturn, error) {
|
||||
ret := UploadReturn{}
|
||||
|
||||
//打开文件句柄操作
|
||||
fileHandle, err := os.Open(arg.LocalFile)
|
||||
if err != nil {
|
||||
return ret, errors.New("superfile2 open file failed")
|
||||
}
|
||||
defer fileHandle.Close()
|
||||
|
||||
// 获取文件当前信息
|
||||
fileInfo, err := fileHandle.Stat()
|
||||
if err != nil {
|
||||
return ret, err
|
||||
}
|
||||
|
||||
// 读取文件块
|
||||
buf := make([]byte, fileInfo.Size())
|
||||
n, err := fileHandle.Read(buf)
|
||||
if err != nil {
|
||||
if err != io.EOF {
|
||||
return ret, err
|
||||
}
|
||||
}
|
||||
|
||||
bodyBuf := &bytes.Buffer{}
|
||||
bodyWriter := multipart.NewWriter(bodyBuf)
|
||||
fileWriter, err := bodyWriter.CreateFormFile("file", "file")
|
||||
if err != nil {
|
||||
return ret, err
|
||||
}
|
||||
|
||||
//iocopy
|
||||
_, err = io.Copy(fileWriter, bytes.NewReader(buf[0:n]))
|
||||
if err != nil {
|
||||
return ret, err
|
||||
}
|
||||
|
||||
bodyWriter.Close()
|
||||
|
||||
protocal := "https"
|
||||
host := "d.pcs.baidu.com"
|
||||
router := "/rest/2.0/pcs/superfile2?method=upload&"
|
||||
uri := protocal + "://" + host + router
|
||||
|
||||
params := url.Values{}
|
||||
params.Set("access_token", accessToken)
|
||||
params.Set("path", arg.Path)
|
||||
params.Set("uploadid", arg.UploadId)
|
||||
params.Set("partseq", strconv.Itoa(arg.Partseq))
|
||||
uri += params.Encode()
|
||||
|
||||
contentType := bodyWriter.FormDataContentType()
|
||||
headers := map[string]string{
|
||||
"Host": host,
|
||||
"Content-Type": contentType,
|
||||
}
|
||||
|
||||
body, _, err := utils.SendHTTPRequest(uri, bodyBuf, headers)
|
||||
if err != nil {
|
||||
return ret, err
|
||||
}
|
||||
if err := json.Unmarshal([]byte(body), &ret); err != nil {
|
||||
return ret, errors.New("unmarshal body failed")
|
||||
|
||||
}
|
||||
if ret.Md5 == "" {
|
||||
return ret, errors.New("md5 is empty")
|
||||
|
||||
}
|
||||
return ret, nil
|
||||
}
|
|
@ -0,0 +1,93 @@
|
|||
package utils
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/tls"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Request struct {
|
||||
Host string
|
||||
Route string
|
||||
QueryArg interface{}
|
||||
Body interface{}
|
||||
Headers map[string]string
|
||||
}
|
||||
|
||||
func DoHTTPRequest(url string, body io.Reader, headers map[string]string) (string, int, error) {
|
||||
timeout := 5 * time.Second
|
||||
retryTimes := 3
|
||||
tr := &http.Transport{
|
||||
MaxIdleConnsPerHost: -1,
|
||||
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
|
||||
}
|
||||
httpClient := &http.Client{Transport: tr}
|
||||
httpClient.Timeout = timeout
|
||||
req, err := http.NewRequest("POST", url, body)
|
||||
if err != nil {
|
||||
return "", 0, err
|
||||
}
|
||||
// request header
|
||||
for k, v := range headers {
|
||||
req.Header.Add(k, v)
|
||||
}
|
||||
|
||||
var resp *http.Response
|
||||
for i := 1; i <= retryTimes; i++ {
|
||||
resp, err = httpClient.Do(req)
|
||||
if err == nil {
|
||||
break
|
||||
}
|
||||
if i == retryTimes {
|
||||
return "", 0, err
|
||||
}
|
||||
}
|
||||
|
||||
defer resp.Body.Close()
|
||||
respBody, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return "", resp.StatusCode, err
|
||||
}
|
||||
return string(respBody), resp.StatusCode, nil
|
||||
}
|
||||
|
||||
// for superfile2
|
||||
func SendHTTPRequest(url string, body io.Reader, headers map[string]string) (string, int, error) {
|
||||
timeout := 60 * time.Second
|
||||
retryTimes := 3
|
||||
postData, _ := ioutil.ReadAll(body)
|
||||
var resp *http.Response
|
||||
for i := 1; i <= retryTimes; i++ {
|
||||
tr := &http.Transport{
|
||||
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
|
||||
MaxIdleConnsPerHost: -1,
|
||||
}
|
||||
httpClient := &http.Client{Transport: tr}
|
||||
httpClient.Timeout = timeout
|
||||
req, err := http.NewRequest("POST", url, bytes.NewBuffer(postData))
|
||||
if err != nil {
|
||||
return "", 0, err
|
||||
}
|
||||
// request header
|
||||
for k, v := range headers {
|
||||
req.Header.Add(k, v)
|
||||
}
|
||||
resp, err = httpClient.Do(req)
|
||||
if err == nil {
|
||||
break
|
||||
}
|
||||
if i == retryTimes {
|
||||
return "", 0, err
|
||||
}
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
respBody, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return "", resp.StatusCode, err
|
||||
}
|
||||
|
||||
return string(respBody), resp.StatusCode, nil
|
||||
}
|
Loading…
Reference in New Issue