百度PCS指百度云,接口需要申请才可以使用。
这里仅记录使用python把文件上传到baiduPCS的过程和代码。官方文档请参考:baidu
基本描述
与官方文档相同或不相同的一些描述
上传流程
文件上传分为三个阶段:预上传、分片上传、创建文件。只有完成这三步,才能将文件上传到网盘。
上传文件夹限制
每个第三方在网盘只能拥有一个文件夹用于存储上传文件,该文件夹必须位于/apps
目录下,apps下的文件夹名称为申请接入填写的申请接入的产品名称
,假如你申请接入的产品名称为”云存储“,那么该文件夹为/apps/云存储
,用户看到的文件夹为/我的应用数据/云存储
。
实际测试时(2021-11-20)可以上传至任意目录。
上传文件限制
大小限制
普通用户单个上传文件大小上限为4G
会员用户单个上传文件大小上限为10G
超级会员用户单个上传文件大小上限为20G
分片大小
- 普通用户单个分片大小固定为4MB(文件大小如果小于4MB,无需切片,直接上传即可),单文件总大小上限为4G。
- 普通会员用户单个分片大小上限为16MB,单文件总大小上限为10G。
- 超级会员用户单个分片大小上限为32MB,单文件总大小上限为20G。
为此,综合来看,可以设计为分片固定为4MB。
完整上传代码
这里不实现获取token的过程,假设为固定值。
以下为python实现代码:
import math
import requests
import os
import hashlib
from urllib.parse import quote
# 百度网盘上传python脚本,可使用bp3获取access_token
# 指定文件名称,以及上传到服务器目录(任意目录均可,不存在时自动生成目录)
def getToken():
token = "121.9b456546a19ed375dd1412be647417df.YCWcEETsGp03isaFKmUhiNS3Gas4Llt9D4234df"
return token
# 计算文件的md5
def getMd5(file_name, filesize, slice):
# 取得应分片数量
number = math.ceil(filesize / slice)
fileLocalMd5List = "["
with open(file_name, 'rb') as fp:
for i in range(number):
data = fp.read(slice)
fileLocalMd5 = hashlib.md5(data).hexdigest()
fileLocalMd5List += '"'
fileLocalMd5List += fileLocalMd5
fileLocalMd5List += '"'
if i < number - 1:
fileLocalMd5List += ","
fileLocalMd5List += "]"
return fileLocalMd5List
# 调用预上传接口
def preCreate(access_token, serverPath, filesize, md5):
print("precreate...")
url = "http://pan.baidu.com/rest/2.0/xpan/file?method=precreate&access_token=" + access_token
payload = {'path': serverPath,
'size': filesize,
'rtype': '1',
'isdir': '0',
'autoinit': '1',
'block_list': '' + md5 + ''}
files = [
]
headers = {
'Cookie': 'BAIDUID=56BE0870011A115CFA43E19EA4CE92C2:FG=1; BIDUPSID=56BE0870011A115CFA43E19EA4CE92C2; PSTM=1535714267'
}
response = requests.request("POST", url, headers=headers, data=payload, files=files)
uploadId = response.json()['uploadid']
blockList = response.json()['block_list']
print(response.json())
return uploadId, blockList
# 文件上传
def upload(access_token, serverPath, uploadId, partSeq, data):
print("upload, slice:" + str(partSeq+1) + "...")
url = "https://d.pcs.baidu.com/rest/2.0/pcs/superfile2?method=upload&access_token=" + access_token + "&path=" + serverPath + "&type=tmpfile&uploadid=" + uploadId + "&partseq=" + str(
partSeq)
payload = {}
files = [
('file', data)
]
headers = {
'Cookie': 'BAIDUID=56BE0870011A115CFA43E19EA4CE92C2:FG=1; BIDUPSID=56BE0870011A115CFA43E19EA4CE92C2; PSTM=1535714267'
}
response = requests.request("POST", url, headers=headers, data=payload, files=files)
print(response.json())
return response.json()['md5']
# 创建文件
def create(access_token, serverPath, filesize, uploadId, blockList):
print("create....")
url = "https://pan.baidu.com/rest/2.0/xpan/file?method=create&access_token=" + access_token
payload = {'path': serverPath,
'size': filesize,
'rtype': '1',
'isdir': '0',
'uploadid': uploadId,
'block_list': blockList}
files = [
]
headers = {
'Cookie': 'BAIDUID=56BE0870011A115CFA43E19EA4CE92C2:FG=1; BIDUPSID=56BE0870011A115CFA43E19EA4CE92C2; PSTM=1535714267'
}
response = requests.request("POST", url, headers=headers, data=payload, files=files)
print(response.text.encode('utf8'))
# 文件上传完整方法
def main(fileDirectory,fileName,uploadDirectory):
# 每次读取4MB(1024*1042*4)
slice = 4194304
# 本地文件
filePath = fileDirectory + fileName
print("本地文件路径:"+filePath)
filesize = os.path.getsize(filePath) # 取得文件大小
print("文件大小:"+str(filesize))
# 上传后的文件
serverPath = uploadDirectory + fileName
encodeServerPath = quote(serverPath)
print("预上传网盘目录:"+serverPath)
# 获取access_token
access_token = getToken()
# 先分片,预上传接口的md5数量指定了分片上传的数量
file_md5 = getMd5(filePath, int(filesize), slice)
# 预上传接口
upLoadId, blockList = preCreate(access_token, encodeServerPath, filesize, file_md5)
if (blockList == []): # 官方文档描述:返回[]时相当于[0]
blockList.append(0)
# 文件上传
print("共需要上传"+str(len(blockList))+"个分片...")
file = open(filePath, "rb")
serverListMd5 = "["
for num in blockList:
data = file.read(slice)
servermd5 = upload(access_token, encodeServerPath, upLoadId, num, data)
serverListMd5 += '"'
serverListMd5 += servermd5
serverListMd5 += '"'
if num < len(blockList) - 1:
serverListMd5 += ","
serverListMd5 += "]"
# 创建文件
create(access_token, serverPath, filesize, upLoadId, serverListMd5)
print("文件上传完毕...")
if __name__ == "__main__":
# 本地文件目录,格式如:C:\\Users\\Administrator\\Downloads\\
fileDirectory = "C:\\Users\\Administrator\\Downloads\\"
# 本地文件名称,格式如:bp3_ua.zip
fileName = "python-3.7.3-amd64.exe"
# 上传到网盘的目录,格式如:/bp3-back/test/
uploadDirectory = "/bp3-back/test/"
main(fileDirectory, fileName, uploadDirectory)
实际测试:
本地文件路径:C:\Users\Administrator\Downloads\python-3.7.3-amd64.exe 文件大小:26190920 预上传网盘目录:/bp3-back/test/python-3.7.3-amd64.exe precreate... {'errno': 0, 'return_type': 1, 'block_list': [0, 1, 2, 3, 4, 5, 6], 'uploadid': 'P1-MTAuNDAuMTU5LjEyOjE2MzczOTI3NTk6ODY1OTAxMDEwNzU3MzU2NzQ5Ng==', 'request_id': 8659010107573567496} 共需要上传7个分片... upload, slice:1... {'md5': '7cf11ad7dc8f4fefc137d08d06e52809', 'request_id': 7506088767047428075} upload, slice:2... {'md5': '7fda08e4c7899e2fb0c545a9e903893e', 'request_id': 7506090506798252745} upload, slice:3... {'md5': 'eaa1d62672bee8d762124279713902ad', 'request_id': 7506092605142990779} upload, slice:4... {'md5': '81f44475262968cb896e6119d14591da', 'request_id': 7506094592625965235} upload, slice:5... {'md5': '7a44451c15c5ee68282a57e555028d82', 'request_id': 7506096567748388287} upload, slice:6... {'md5': '055bc4eaadd74d4e64d028f762a76f43', 'request_id': 7506098683585957329} upload, slice:7... {'md5': '28f2926795f965580048d6c22d504030', 'request_id': 7506100948422304128} create.... b'{"ctime":1637392807,"from_type":1,"fs_id":1030842997265730,"isdir":0,"md5":"201ab2b80hbcf6514173303ed400fdfc","mtime":1637392807,"path":"\\/bp3-back\\/test\\/python-3.7.3-amd64.exe","size":26190920,"errno":0,"name":"\\/bp3-back\\/test\\/python-3.7.3-amd64.exe","category":6}' 文件上传完毕...
本篇完,还有疑问?留下评论吧