奉行长期主义的开发者都有一个共识:对于服务器来说,数据备份非常重要,因为服务器上的数据通常是无价的,如果丢失了这些数据,可能会导致严重的后果,伴随云时代的发展,备份技术也让千行百业看到了其“云基因”的成长与进化,即基于云存储的云备份。

本次我们使用Golang1.18完成百度网盘(百度云盘)接口API自动化备份上传功能,以及演示如何将该模块进行开源发布。

百度网盘API接入授权

如果希望golang服务可以访问并且上传用户的百度网盘,则需要经过用户同意,这个流程被称为“授权”。百度网盘开放平台基于 OAuth2.0 接入授权。OAuth2.0 是一种授权协议,通过该协议用户可以授权开发者应用访问个人网盘信息与文件。

用户同意授权后,开发者应用会获取到一个 Access Token,该 Access Token 是用户同意授权的凭证。开发者应用需要依赖 Access Token 凭证调用百度网盘公开API,实现访问用户网盘信息与授权资源。

基本流程和三方登录差不多,需要跳转百度网盘授权页进行授权动作,随后授权码(code)会发送到回调网址,再用授权码换取Access Token。但不一样的是,百度官网提供一种相对简单的获取code方式,即oob,所谓oob就是直接在线请求后在表单中复制授权码即可,不需要回调网址的参与。

首先根据官网文档:https://pan.baidu.com/union/doc/ol0rsap9s 创建应用,创建好之后,将应用id拼接位oob授权网址:

https://openapi.baidu.com/oauth/2.0/authorize?client_id=你的应用id&response_type=code&redirect_uri=oob&scope=basic+netdisk

在线访问复制授权码:

注意授权码一次性有效并且会在10分钟后过期,随后编写代码获取token:

package bdyp  import (  "fmt"  "net/http"  "net/url"
)  type Bcloud struct {  app_key      string  app_secret   string  accessToken  string  refreshToken string  logger       Logger
}  type tokenResp struct {  *Token  ErrorDescription string `json:"error_description"`
}  type Token struct {  AccessToken  string `json:"access_token"`  RefreshToken string `json:"refresh_token"`  ExpiresIn    int    `json:"expires_in"`
}  func (r *Bcloud) GetToken(code, redirectURI, app_key, app_secret string) (*Token, error) {  uri := fmt.Sprintf("https://openapi.baidu.com/oauth/2.0/token?"+  "grant_type=authorization_code&"+  "code=%s&"+  "client_id=%s&"+  "client_secret=%s&"+  "redirect_uri=%s",  url.QueryEscape(code),  url.QueryEscape(app_key),  url.QueryEscape(app_secret),  redirectURI)  resp := new(tokenResp)  err := r.requestJSON(http.MethodGet, uri, nil, resp)  if err != nil {  return nil, err  } else if resp.ErrorDescription != "" {  return nil, fmt.Errorf(resp.ErrorDescription)  }  r.app_key = app_key  r.app_secret = app_secret  r.accessToken = resp.AccessToken  r.refreshToken = resp.RefreshToken  return resp.Token, nil
}

这里分别创建网盘结构体和秘钥结构体,通过官方接口将oob方式获取的code交换token,分别为accessToken和refreshToken,refreshToken用于刷新 Access Token, 有效期为10年。

这里最好将token写入文件或者存入数据库,本文只讨论授权和上传逻辑,故不加入数据库的相关操作。

至此,百度网盘的授权操作就完成了。

服务器本地文件上传至百度网盘

根据官网文档描述:https://pan.baidu.com/union/doc/3ksg0s9ye,上传流程是指,用户将本地文件上传到百度网盘云端服务器的过程。文件上传分为三个阶段:预上传、分片上传、创建文件。第二个阶段分片上传依赖第一个阶段预上传的结果,第三个阶段创建文件依赖第一个阶段预上传和第二阶段分片上传的结果,串行完成这三个阶段任务后,本地文件成功上传到网盘服务器。

说白了,有点像HTTP连接的三次握手,目的就是为了保证上传数据的完整性,强制串行的原子操作也有利于保证上传任务的可靠性。

首先构建预上传函数:

func (r *Bcloud) FileUploadSessionStart(req *FileUploadSessionStartReq) (*FileUploadSessionStartResp, error) {  token, err := r.getAuthToken()  if err != nil {  return nil, err  }  req.Method = "precreate"  req.AccessToken = token  req_, err := req.to()  if err != nil {  return nil, err  }  resp := new(FileUploadSessionStartResp)  err = r.requestURLEncode(http.MethodPost, "https://pan.baidu.com/rest/2.0/xpan/file", req_, resp)  if err != nil {  return nil, err  } else if err := resp.Err(); err != nil {  return nil, err  }  if len(resp.BlockList) == 0 {  resp.BlockList = []int64{0}  }  return resp, nil
}

这里参数为预上传参数的结构体:

type FileUploadSessionStartReq struct {  Method      string `query:"method"`  AccessToken string `query:"access_token"`  Path        string `json:"path"`  File        io.Reader  RType       *int64 `json:"rtype"`
}

随后是分片上传逻辑:

func (r *Bcloud) FileUploadSessionAppend(req *FileUploadSessionAppendReq) error {  token, err := r.getAuthToken()  if err != nil {  return err  }  req.Method = "upload"  req.AccessToken = token  req.Type = "tmpfile"  resp := new(fileUploadSessionAppendResp)  err = r.requestForm(http.MethodPost, "https://d.pcs.baidu.com/rest/2.0/pcs/superfile2", req, resp)  if err != nil {  return err  } else if err := resp.Err(); err != nil {  return err  } else if resp.ErrorMsg != "" {  return fmt.Errorf(resp.ErrorMsg)  }  return nil
}  type FileUploadSessionAppendReq struct {  Method      string    `query:"method"` // 本接口固定为precreate  AccessToken string    `query:"access_token"`  Type        string    `query:"type"`     // 固定值 tmpfile  Path        string    `query:"path"`     // 需要与上一个阶段预上传precreate接口中的path保持一致  UploadID    string    `query:"uploadid"` // 上一个阶段预上传precreate接口下发的uploadid  PartSeq     int64     `query:"partseq"`  // 文件分片的位置序号,从0开始,参考上一个阶段预上传precreate接口返回的block_list  File        io.Reader `file:"file"`      // 是     RequestBody参数   上传的文件内容
}

对于总体积大于4mb的文件,通过切片的方式进行上传。

总后是合并文件写入文件逻辑:

func (r *Bcloud) FileUploadSessionFinish(req *FileUploadSessionFinishReq) error {  token, err := r.getAuthToken()  if err != nil {  return err  }  req.Method = "create"  req.AccessToken = token  req_, err := req.to()  if err != nil {  return err  }  resp := new(fileUploadSessionFinishResp)  err = r.requestURLEncode(http.MethodPost, "https://pan.baidu.com/rest/2.0/xpan/file", req_, resp)  if err != nil {  return err  } else if err := resp.Err(); err != nil {  return err  }  return nil
}  type FileUploadSessionFinishReq struct {  Method      string    `query:"method"`  AccessToken string    `query:"access_token"`  Path        string    `json:"path"`  File        io.Reader `json:"-"`  UploadID    string    `json:"uploadid"`  RType       *int64    `json:"rtype"`
}

至此,完成了文件上传的三个阶段:预上传、分片上传、创建文件。

开源发布Publish

我们知道在 Golang的项目中,可以 import 一个托管在远程仓库的模块,这个模块在我们使用 go get 的时候,会下载到本地。既然是放在远程仓库上,意味着所有人都可以发布,并且所以人也都可以使用,所以为了让乡亲们更方便地上传数据到百度网盘,让我们把这个项目开源。

先在你的 Github 上新建一个仓库,记得选 Public(公开项目),随后将项目代码推送到Github上面:

echo "# bdyp_upload_golang" >> README.md
git init
git add README.md
git commit -m "first commit"
git branch -M main
git remote add origin https://github.com/zcxey2911/bdyp_upload_golang.git
git push -u origin main

在项目根目录使用go mod init 命令进行初始化,注意这里的模块名,填写我们的git仓库名称,但是不要带着.git:

go mod init github.com/zcxey2911/bdyp_upload_golang

再次推送项目模块代码:

git add -A
git commit -m "Add a go mod file"
git push -u origin main

全部完成以后,刷新我们的仓库,就可以看到我们的刚刚上传的项目代码了,点击 release 发布一个版本即可。

最后,通过go get命令安装发布之后的模块:

go get github.com/zcxey2911/bdyp_upload_golang

完整的调用流程:

package main  import (  "fmt"  bdyp "github.com/zcxey2911/bdyp_upload_golang"  "os"
)  func main() {  var bcloud = bdyp.Bcloud{}  // 获取token  res, err := bcloud.GetToken("oob获取的code", "oob", "应用appkey", "应用appsecret")  fmt.Println(res)  if err != nil {  fmt.Println("err", err)  } else {  fmt.Printf("接口的token是: %#v\n", res.AccessToken)  }  // 读取文件  f, err := os.Open("/Users/liuyue/Downloads/ju1.webp")  if err != nil {  fmt.Println("err", err)  return  }  defer f.Close()  // 上传文件  print(bcloud.Upload(&bdyp.FileUploadReq{  Name:  "/apps/云盘备份/ju2.webp",  File:  f,  RType: nil,  }))  }

查看上传的数据:

简单快速,一气呵成。

结语

当然了百度云盘备份也不是没有缺陷,将数据存储在云端可能会存在安全性和隐私性问题,与此同时,数据量很大或者数据分布在不同地点的情况下,恢复数据所需的时间会比较长。不差钱的同学也可以选择磁盘快照服务,最后奉上项目地址,与君共勉:https://github.com/zcxey2911/bdyp_upload_golang

防微杜渐,未雨绸缪,百度网盘(百度云盘)接口API自动化备份上传以及开源发布,基于Golang1.18相关推荐

  1. AList和RaiDrive对百度网盘进行本地挂载(可上传下载)

    简介: 为了实现百度网盘以及实现Office打开的本地路径选择能多出来一个百度网盘的路径,我千方百计寻找解决方案,一开始实现挂载和在线查看百度网盘内的小文件,大型文件速度极慢:但是有一个始终无法解决的 ...

  2. synology服务器限制用户复制文件,百度网盘限制群晖NAS用户上传数据,免费时代结束了...

    群晖系统真是一个很好用的系统,目前我的蜗牛星际主机组装的黑群晖已经运行2个月了,十分便利.大家都说 不过群晖同步 百度网盘给出的官方通知显示,可供 原本"百度网盘后宫佳丽三千,独独宠群晖一人 ...

  3. php对接百度网盘开发平台API开发高级实战案例解析:(环境部署、php封装类、Access Token获取、预上传、分片上传)

    文章目录 前言 一.环境部署 1.封装BdPan类库 2.回调地址配置 二.获取授权码Code 1.手动获取Code 2.生成本地token 3.读取AccessToken凭证 4.爬虫函数 二.简化 ...

  4. 百度网盘小程序互转工具:wx2正式开源!

    " 2020年11月,百度网盘小程序互转工具WX2,正式开源!" wx2是一个小程序的转换工具,它可以一键将原生的微信小程序转化成百度小程序.作为一种轻量级小程序跨宿主解决方案,w ...

  5. android电视查看百度网盘,如何将手机百度网盘视频投屏到电视上观看?

    原标题:如何将手机百度网盘视频投屏到电视上观看? 点击上方运营进化岛 "设为星标"⭐ 电视是我新家最后置办的一个大家电,因为觉得使用率会特别低,摆在那里落灰,犹豫要不要买.现在追剧 ...

  6. 将电脑文件备份到百度网盘,并实现自动备份

    如何将电脑文件备份到百度网盘,并且定时自动备份?大家都有相同的习惯,平时我们都喜欢用百度网盘来存储文件,因为百度网盘属于线上存储器,文件备份到百度网盘之后,不管我人在哪里,只要登录账号,就能下载自己需 ...

  7. python 网络文件传输(邮件+百度网盘(百度云盘)+阿里云盘)

    邮件(以QQ邮箱为例) 发件人开启POP3/SMTP 邮箱设置->账户(新版本的在常规中)->POP3/IMAP/SMTP/Exchange/CardDAV/CalDAV服务 有的账号登陆 ...

  8. 百度网盘良心了!非会员轻松上30MB/s,且用且珍惜!

    百度网盘是如今国内最大的在线存储服务提供商,用户体量越来越大,为了盈利变现APP客户端早已加入各种广告及推广服务.其实限速可以理解,企业需要考虑运营成本,但人家充会员依旧几十KB的速度,甚至开超级会员 ...

  9. 电脑文件夹备份到百度网盘,可以实现自动备份

    电脑文件夹怎么备份到百度网盘?我们经常需要将电脑上的重要文件进行备份,备份可以保证数据安全,以减轻因为文件丢失而带来的顺出.百度网盘是一种非常不错的文件云存储介质,所以很多小伙伴希望能将电脑文件备份到 ...

最新文章

  1. [转]LIB和DLL的区别与使用
  2. Ajax入门(创建 XMLHttpRequest 对象)
  3. asp.net C#后台实现下载文件的几种方法
  4. SSE3指令集系列----数据加载与算术运算指令
  5. 王爽《汇编语言》笔记(详细)
  6. 手机群控系统电脑/手机硬件配置相关测试参数
  7. 一个月攻克托业--复旦大学考生
  8. Contextual Diversity for Active Learning阅读笔记
  9. 深度思考:广州互联网气氛为何远远落后于北京
  10. 勒索软件Cerber和TeslaCrypt的区别-------典型的勒索软件家族
  11. 【android】悬浮球
  12. 将加密的ppt文档解密,使之可以编辑
  13. Lenet、Alexnet 、VGG、 GoogleNet、ResNet模型
  14. BK05-蓝鲸智云-标准部署-关键模块逐步操作
  15. HTML+CSS+JS网页设计期末课程大作业(家居网)
  16. 启动gazebo报错提示[gazebo_gui-3] process has died [pid 3366
  17. 属性加密(ABE)基础知识
  18. 更加方便获取eid和fp的一种方式-通过HTML文件
  19. Hash MSDN MD4 MD5 SHA1 CRC 详细解释
  20. 安装easyswoole(宝塔坑)

热门文章

  1. 基本磁场计算公式的简单推导
  2. 【Axure教程】橡皮擦的擦除效果——刮奖原型
  3. linux axel rpm,CentOS 5/6下安装Axel插件加速yum下载
  4. 网络地址分类(公网地址和私有地址)
  5. 程序设计【Week9】作业
  6. Splinter入门(三) Finding Elements 查找元素
  7. Splinter入门(六) links的API
  8. 一级注册消防工程师备考解答:注册消防工程师好考吗?
  9. js数组求和的方法(最高效率)
  10. C语言if语句判断素数,利用简单的if语句判断素数