当前位置: 首页 > python>阅读正文

python上传文件到baiduPCS

2021.11.23 朱丰华 1404 次 留下评论 5380字

百度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}'
文件上传完毕...

本篇完,还有疑问?留下评论吧

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注