App Inventor 2 百度网盘拓展:授权、文件列表、下载、上传

« 返回首页

更新日志

  • v1.0
    • 首发:授权地址生成与回调解析、文件列表、文件信息、下载链接、下载文件、分片上传。
    • 接口出错(包括 access_token 过期)统一触发 ApiError,给出中文原因。

拓展下载

拓展组件名:BaiduPan,类名 cn.fun123.BaiduPan.BaiduPan。

想了解用 Web客户端 自己拼接口的原理,请看:App Inventor 2 接入百度网盘API

使用前准备

  1. 在 百度网盘开放平台 创建应用,拿到 AppKey(AppID 可选,SecretKey 用不到)。
  2. 把 AppKey 填到组件的 AppKey 属性。
  3. 让用户在 App 里登录授权一次,拿到 access_token(有效期约 30 天,建议存进微数据库,过期再重新授权)。

上传有一个限制:第三方应用只能写入网盘的 /apps/应用名称/ 目录(应用名称是在开放平台创建应用时填的名字),往其它目录上传会报「无权访问」。读取和下载不受此限制。

使用示例

以下示例用到按钮、标签、列表显示框、Web浏览框、Web客户端(解析 JSON)和微数据库等原生组件。

1. 用户授权,拿到 access_token

用 Web浏览框 打开授权页,用户登录并同意后,页面会跳转到带 access_token 的回调地址,从地址里取出来保存即可。 下次打开 App 先从微数据库读,读到了就不用再授权。

when Screen1.Initialize() {
  BaiduPan1.AccessToken = TinyDB1.GetValue("pan_token", "")
  if isEmpty(BaiduPan1.AccessToken) {
    WebViewer1.Visible = true
    WebViewer1.GoToUrl(BaiduPan1.AuthorizationUrl())
  }
}

when WebViewer1.PageLoaded(url) {
  if textContains(url, "access_token=") {
    BaiduPan1.ExtractAccessToken(url)
  }
}

when BaiduPan1.AccessTokenChanged(token) {
  TinyDB1.StoreValue("pan_token", token)
  WebViewer1.Visible = false
  标签_状态.Text = "授权成功"
}

2. 列出目录文件

FilesListed 返回的是接口原始 JSON,文件在 list 数组里,server_filename 是文件名、fs_id 是文件编号(下载要用)、isdir 为 1 表示目录。

global fileIds = []

when 按钮_列表.Click() {
  BaiduPan1.ListFiles("/")
}

when BaiduPan1.FilesListed(dir, json) {
  var data = Web1.JsonTextDecodeWithDictionaries(json)
  var names = []
  fileIds = []
  foreach item in dictGet(data, "list", []) {
    listAdd(names, dictGet(item, "server_filename", ""))
    listAdd(fileIds, dictGet(item, "fs_id", ""))
  }
  列表显示框1.Elements = names
}

3. 下载选中的文件

直接用 fs_id 下载,拓展会先取下载链接再下载,保存路径请用绝对路径(如 /storage/emulated/0/Download/xxx,或应用专属目录)。

when 列表显示框1.AfterPicking() {
  var fsId = selectListItem(fileIds, 列表显示框1.SelectionIndex)
  标签_状态.Text = "下载中…"
  BaiduPan1.DownloadByFsId(fsId, join("/storage/emulated/0/Download/", 列表显示框1.Selection))
}

when BaiduPan1.DownloadSuccess(savePath, bytesWritten) {
  标签_状态.Text = join("已保存:", savePath, ",", bytesWritten, " 字节")
}

4. 上传文件

大文件会按 4MB 分片上传,UploadProgress 报告分片进度。远程路径需以 /apps/应用名称/ 开头;replaceMode 为 3 时同名文件直接覆盖。

when 按钮_上传.Click() {
  BaiduPan1.UploadFile("/apps/我的应用/备份.txt", "/storage/emulated/0/Download/备份.txt", 3)
}

when BaiduPan1.UploadProgress(remotePath, uploadedParts, totalParts) {
  标签_状态.Text = join("上传中 ", uploadedParts, "/", totalParts)
}

when BaiduPan1.UploadSuccess(remotePath, json) {
  标签_状态.Text = join("上传完成:", remotePath)
}

5. 处理错误

所有失败都走 ApiError:网络不通、参数为空、access_token 过期、文件不存在等,message 是中文原因。 过期时 message 会提示「请重新授权」,此时清掉保存的 token 重新授权即可。

when BaiduPan1.ApiError(operation, httpStatus, message, responseBody) {
  标签_状态.Text = message
  if textContains(message, "重新授权") {
    TinyDB1.ClearTag("pan_token")
    WebViewer1.Visible = true
    WebViewer1.GoToUrl(BaiduPan1.AuthorizationUrl())
  }
}

属性

AccessToken
当前使用的 access_token。授权后由 ExtractAccessToken 自动写入,也可以把之前保存的值直接赋给它。
AppId
百度开放平台应用的 AppID(可选,目前接口用不到)。
AppKey
百度开放平台应用的 AppKey,生成授权地址必填。
DefaultScope
授权时申请的权限范围,默认 basic,netdisk,一般不用改。
UserAgent
接口请求使用的 User-Agent,默认 pan.baidu.com。下载文件时固定使用 pan.baidu.com(百度网盘的要求),不受此属性影响。

事件

AccessTokenChanged(token)
调用 ExtractAccessToken 成功取到 token 并写回 AccessToken 属性后触发。
ApiError(operation,httpStatus,message,responseBody)
任一操作失败时触发。operation 为出错的方法名;httpStatus 为 HTTP 状态码(百度接口出错时通常仍是 200,原因看 message;非网络错误为 -1); message 为中文原因(含百度错误码 errno);responseBody 为接口原始返回内容。
DownloadLinkReceived(fsId,dlink,json)
GetDownloadLink 成功时触发,dlink 为下载链接(有效期约 8 小时),json 为接口原始返回。
DownloadSuccess(savePath,bytesWritten)
下载完成时触发,bytesWritten 为文件字节数。下载失败触发 ApiError,且不会留下不完整的文件。
FileMetasReceived(json)
GetFileMetas 成功时触发,json 为接口原始返回(list 数组里是每个文件的详细信息)。
FilesListed(dir,json)
ListFiles / ListFilesEx 成功时触发,json 为接口原始返回,文件在 list 数组里。
UploadProgress(remotePath,uploadedParts,totalParts)
上传时每完成一个分片(4MB)触发一次。
UploadSuccess(remotePath,json)
上传完成时触发,json 为创建文件接口的原始返回(含 fs_id、path 等)。

方法

AuthorizationUrl()
用当前 AppKey 与 DefaultScope 生成授权地址,交给 Web浏览框 打开。没设 AppKey 时返回空文本并触发 ApiError。
AuthorizationUrlWithScope(scope)
生成指定权限范围的授权地址;scope 为空时使用 DefaultScope。
用下载链接下载文件到本地 savePath(绝对路径,目录不存在会自动创建)。拓展会自动附加 access_token。
DownloadByFsId(fsId,savePath)
用文件编号下载:先取下载链接再下载到本地 savePath。
ExtractAccessToken(redirectUrl)
从授权回调地址里取出 access_token,写回 AccessToken 属性并触发 AccessTokenChanged。 地址里没有 token(用户取消授权、页面还没跳到回调地址)时返回空文本并触发 ApiError。
ExtractExpiresIn(redirectUrl)
从授权回调地址里取出有效期秒数 expires_in,没有时返回空文本。
获取单个文件的下载链接,结果在 DownloadLinkReceived 事件里。
GetFileMetas(fsIdsJson)
获取一个或多个文件的详细信息,参数为文件编号的 JSON 数组文本,如 [1737895653506,1737895653507]。
ListFiles(dir)
列出目录文件,按修改时间倒序,取前 100 个。
ListFilesEx(dir,start,limit,order,desc,foldersOnly)
列出目录文件(完整参数):从第 start 个开始取 limit 个(分页用);order 为排序字段 time / name / size;desc 为真时倒序;foldersOnly 为真时只列目录。
UploadFile(remotePath,localFilePath,replaceMode)
上传本地文件(绝对路径,不支持直接用素材文件)到网盘 remotePath(需以 /apps/应用名称/ 开头)。 replaceMode 为同名文件处理方式:0 报错、1 自动重命名、2 内容不同才重命名、3 覆盖。

常见问题

Q:列文件、下载一直报「身份验证失败,请重新授权」?

A:access_token 过期(约 30 天)或者填错了,按示例 1 重新授权即可。


Q:上传报「文件或目录名错误,或无权访问」?

A:第三方应用只能上传到 /apps/应用名称/ 目录下,检查远程路径的开头。


Q:支持自动刷新 token 吗?

A:不支持。本拓展用的是简化授权模式(不需要 SecretKey,适合纯 App),token 到期后请让用户重新授权。

文档反馈