工具-百度云盘服务-常用能力

目标

  1. 查询用户信息及容量
  2. 文件管理,支持创建/复制/转移/删除/重命名
  3. 文件查询
  4. 获取用户指定目录下的文档列表并下载到本地

实现逻辑

  1. 用户信息主要是用于确认登录的用户是否正确及是否还有容量存储;
  2. 用于快速操作文件,可以对指定的文件进行复制、移动、重命名和删除操作;
  3. 对于一些不清楚位置的文件进行快速的检索;
  4. 将一些需要的文件进行下载到本地,其中需要先从网盘获取到文件,通过查询文件信息获取文件的下载地址(该地址有效期只有8小时),通过下载地址将文件并发下载到本地;

代码实现

  1. 用于获取用户的基本信息,包括账号、头像地址、会员类型等
    获取用户的网盘空间的使用情况,包括总空间大小,已用空间和剩余可用空间情况
 # 用户信息 用户容量
    def get_user_info(self):
        api_instance = userinfo_api.UserinfoApi(self.client)
        access_token = self._access_token  # str |
        checkexpire = 1  # 是否检查免费信息,0为不查,1为查,默认为0
        checkfree = 1  # 是否检查过期信息,0为不查,1为查,默认为0
        try:
            userinfo = api_instance.xpannasuinfo(access_token)
            # print(userinfo)
            logging.info(f"用户名:{userinfo['baidu_name']}")
            logging.info(f"授权状态:{userinfo['errmsg']}")
            quota_info = api_instance.apiquota(access_token, checkexpire=checkexpire, checkfree=checkfree)
            # print(quota_info)
            logging.info(f"总容量为:{round(quota_info['total']/1024/1024/1024,2)}G")
            logging.info(f"已使用容量为:{round(quota_info['used']/1024/1024/1024,2)}G")
            return userinfo, quota_info
        except openapi_client.ApiException as e:
            print("获取用户信息失败: %s\n" % e)
  1. 用于对指定的文件进行复制、移动、重命名和删除操作
	# 文件管理 创建 复制 转移 删除 重命名
    # type copy move
    # [{"path": "/test/123456.docx", "dest": "/test/abc", "newname": "11223.docx", "ondup": "fail"}]【copy / move示例】
    # [{"path": "/test/123456.docx", "newname": "123.docx"}]【rename示例】
    # ["/test/123456.docx"]【delete示例】
    # ondup 全局ondup,遇到重复文件的处理策略, fail(默认,直接返回失败)、newcopy(重命名文件)、overwrite、skip
    def file_operate(self, type, path, newname=None, dest=None, ondup='overwrite'):
        api_instance = filemanager_api.FilemanagerApi(self.client)
        access_token = self._access_token # str |
        _async = 1  # int | async 0 同步,1 自适应,2 异步
        try:
            if dest is not None: # 复制/移动
                file_list = json.dumps([{"path": path, "dest":dest, 'newname':newname, 'ondup':ondup }])
                if type == 'copy':
                    copy_response = api_instance.filemanagercopy(access_token,_async,file_list)
                    if copy_response['errno'] == 0:
                        logging.info(f'{path}文件复制到{dest}/{newname}')
                    else:
                        logging.error(f'复制失败:{copy_response}')
                elif type == 'move':
                    move_response = api_instance.filemanagermove(access_token, _async, file_list)
                    if move_response['errno'] == 0:
                        logging.info(f'{path}文件移动到{dest}/{newname}')
                    else:
                        logging.error(f'移动失败:{move_response}')
            elif newname is not None and type == 'rename': # 重命名
                file_list = json.dumps([{'path':path, 'newname':newname}])
                rename_response = api_instance.filemanagerrename(access_token,_async,file_list,ondup=ondup)
                if rename_response['errno'] == 0:
                    logging.info(f'{path}文件重命名为{newname}')
                else:
                    logging.error(f'重命名失败:{rename_response}')
            elif path is not None and type == 'delete': # 删除
                file_list = json.dumps([path])
                delete_response = api_instance.filemanagerdelete(access_token,_async,file_list,ondup=ondup)
                if delete_response['errno'] == 0:
                    logging.info(f'{path}删除成功')
                else:
                    logging.error(f'删除失败:{delete_response}')
            else:
                logging.error(f'未知操作:{type},type:copy/move/rename/delete')
        except openapi_client.ApiException as e:
            logging.error("文件操作异常: %s\n" % e)
  1. 用于获取用户指定目录下,包含指定关键字的文件列表
# 文件查询
    def search(self, key, dir='/', recursion='1', web='1',page='1'):
        api_instance = fileinfo_api.FileinfoApi(self.client)
        access_token = self._access_token
        key = key  # 搜索关键字,最大30字符(UTF8格式)
        web = web  # str |  (optional) | 是否展示缩略图信息,带这个参数会返回缩略图信息,否则不展示缩略图信息
        num = "500"  # str |  (optional) | 默认为500,不能修改
        page = page  # str |  (optional) | 页数,从1开始,缺省则返回所有条目
        dir = dir  # str |  (optional) | 搜索目录,默认根目录
        recursion = recursion  # str |  (optional) | 是否递归,带这个参数就会递归,否则不递归
        try:
            api_response = api_instance.xpanfilesearch(
                access_token, key, web=web, num=num, page=page, dir=dir, recursion=recursion)
            if api_response['errno'] == 0:
                type_list = api_response['list']
                logging.info(f'{dir}目录下搜索关键词为{key}的文件有{len(type_list)}个')
                return type_list
            else:
                logging.error(f'{dir}目录下搜索关键词为{key}文件查询失败:{api_response}')
            # return api_response['']
        except openapi_client.ApiException as e:
            logging.error(f"文件搜索失败: {e}")

  1. 用于获取用户网盘中指定目录下的文件列表。返回的文件列表支持排序、分页等操作
	# 指定目录下文件下载到本地
    def get_dir_file2local(self, dir, local_dir='./tmp/'):
        if not os.path.exists(local_dir):
            os.makedirs(local_dir)
        file_list = self.get_file_list(dir,type='file')
        fs_ids = [file.get('fs_id') for file in file_list]
        # for file in file_list:
        #     fs_ids.append(file.get('fs_id'))
        info_list = self.file_meatas(fs_ids)
        download_infos = []
        for info in info_list:
            dlink = info.get('dlink')
            filename = info.get('filename')
            # size = info.get('size')
            local_path = local_dir+filename
            download_infos.append({'path':local_path, 'url':f'{dlink}&access_token={self._access_token}'})
        # 并发下载
        self.thread_download(download_infos)
        
	# 获取用户指定目录下的文档列表
    # type doc image file
    def get_file_list(self, dir, type, recursion='1', page=1, num=20, order="time", desc='1', web='1',folder='0',showempty=1):
        api_instance = fileinfo_api.FileinfoApi(self.client)
        access_token = self._access_token
        parent_path = dir  # str |  (optional)|目录名称,以/开头的绝对路径, 默认为/路径包含中文时需要UrlEncode编码 给出的示例的路径是/测试目录的UrlEncode编码。
        recursion = recursion  # 是否需要递归,0为不需要,1为需要,默认为0 递归是指:当目录下有文件夹,使用此参数,可以获取到文件夹下面的文档
        page = page  # 页码,从1开始, 如果不指定页码,则为不分页模式,返回所有的结果。如果指定page参数,则按修改时间倒序排列
        num = num  # 一页返回的文档数, 默认值为1000,建议最大值不超过1000
        order = order  # 排序字段:time按修改时间排序,name按文件名称排序(注意,此处排序是按字符串排序的,如果用户有剧集排序需求,需要自行开发),size按文件大小排序,默认为time
        desc = desc  # 0为升序,1为降序,默认为1
        web = web  # 为1时返回文档预览地址lodocpreview
        try:
            if type == 'doc':
                api_response = api_instance.xpanfiledoclist(
                    access_token, parent_path=parent_path, recursion=recursion, page=page, num=num, order=order,
                    desc=desc, web=web)
                if api_response['errno'] == 0:
                    type_list = api_response['info']
                    logging.info(f'{dir}目录下{type}类型的文件有{len(type_list)}个')
                    return type_list
                else:
                    logging.error(f'{dir}目录下{type}类型文件查询失败:{api_response}')
                # pprint(api_response)
            elif type == 'image':
                api_response = api_instance.xpanfileimagelist(
                    access_token, parent_path=parent_path, recursion=recursion, page=page, num=num, order=order,
                    desc=desc, web=web)
                if api_response['errno'] == 0:
                    type_list = api_response['info']
                    logging.info(f'{dir}目录下{type}类型的文件有{len(type_list)}个')
                    return type_list
                else:
                    logging.error(f'{dir}目录下{type}类型文件查询失败:{api_response}')
            elif type == 'file':
                # dir 需要list的目录,以/开头的绝对路径, 默认为/路径包含中文时需要UrlEncode编码 给出的示例的路径是/测试目录的UrlEncode编码
                # folder 是否只返回文件夹,0 返回所有,1 只返回文件夹,且属性只返回path字段
                # start 起始位置,从0开始
                # limit 查询数目,默认为1000,建议最大不超过1000
                # order 排序字段:默认为name; time表示先按文件类型排序,后按修改时间排序; name表示先按文件类型排序,后按文件名称排序;(注意,此处排序是按字符串排序的,如果用户有剧集排序需求,需要自行开发) size表示先按文件类型排序,后按文件大小排序。
                # web 值为1时,返回dir_empty属性和缩略图数据
                # showempty 是否返回dir_empty属性,0 不返回,1 返回
                api_response = api_instance.xpanfilelist(
                    access_token, dir=dir, folder=folder, start=str(page), limit=num, order=order, desc=int(desc), web=web,
                    showempty=showempty)
                if api_response['errno'] == 0:
                    type_list = api_response['list']
                    logging.info(f'{dir}目录下{type}类型的文件有{len(type_list)}个')
                    return type_list
                else:
                    logging.error(f'{dir}目录下{type}类型文件查询失败:{api_response}')
            elif type == 'listall':
                # 递归获取指定目录下的文件列表。当目录下存在文件夹,并想获取到文件夹下的子文件时,可以设置 recursion 参数为1,即可获取到更深目录层级的文件
                api_instance = multimediafile_api.MultimediafileApi(self.client)
                api_response = api_instance.xpanfilelistall(
                    access_token, dir, int(recursion), web=web, start=page, limit=num, order=order, desc=int(desc))
                if api_response['errno'] == 0:
                    type_list = api_response['list']
                    logging.info(f'{dir}目录下递归获取文件有{len(type_list)}个')
                    return type_list
                else:
                    logging.error(f'{dir}目录下递归获取文件查询失败:{api_response}')
        except openapi_client.ApiException as e:
            logging.error(f"获取{type}列表失败:{e}")
	
	# 用于获取用户指定文件的meta信息。支持查询多个或一个文件的meta信息,meta信息包括文件名字、文件创建时间、文件的下载地址等
    def file_meatas(self,fsids):
        api_instance = multimediafile_api.MultimediafileApi(self.client)
        access_token = self._access_token
        fsids = json.dumps(fsids)  # str |
        # path # 查询共享目录或专属空间内文件时需要。 共享目录格式: /uk-fsid 其中uk为共享目录创建者id, fsid对应共享目录的fsid 专属空间格式:/_pcs_.appdata/xpan/
        thumb = "1"  # 是否需要缩略图地址,0为否,1为是,默认为0
        extra = "1"  # 图片是否需要拍摄时间、原图分辨率等其他信息,0 否、1 是,默认0
        dlink = "1"  # 是否需要下载地址,0为否,1为是,默认为0。获取到dlink后,参考下载文档进行下载操作
        needmedia = 1  # 视频是否需要展示时长信息,needmedia=1时,返回 duration 信息时间单位为秒 (s),转换为向上取整。 0 否、1 是,默认0
        detail = 1  # 视频是否需要展示长,宽等信息。 0 否、1 是,默认0
        try:
            api_response = api_instance.xpanmultimediafilemetas(
                access_token, fsids, thumb=thumb, extra=extra, dlink=dlink, needmedia=needmedia)
            # pprint(api_response)
            if api_response['errno'] == 0:
                info_list = api_response['list']
                logging.info(f'通过{fsids}获取文件信息有{len(info_list)}个')
                return info_list
            else:
                logging.error(f'{dir}目录下递归获取文件查询失败:{api_response}')
        except openapi_client.ApiException as e:
            print("Exception when calling MultimediafileApi->xpanmultimediafilemetas: %s\n" % e)

	# 并发下载 将文件下载到本地 dlink有效期为8小时,过期后,dlink失效
    def thread_download(self, download_infos, max_workers=10):
        # 记录下载了多少个url
        file_paths = []
        with ThreadPoolExecutor(max_workers=max_workers) as executor:
            future_results = {}
            for download_info in download_infos:
                path = download_info.get('path')
                url = download_info.get('url')
                fs = executor.submit(ConcurrentDownload.download_file, url, os.path.dirname(path),file_name=path.rsplit('/')[-1],threads=max_workers)
                future_results[fs] = url
            for future in as_completed(future_results):
                file_paths.append(future.result())
                logging.info('总共{}个,下载了{}个'.format(len(download_infos),len(file_paths)))
        return file_paths

总结

上述一些能力都是一些常用的功能,对于大文件来说,一般下载操作都比较耗时,所以我们这边是进行了一个并发下载的操作,可以快速实现下载。以上功能可以方便后期可以快速的和网盘进行交互,从而将我们的各种应用对接到网盘,实现我们最终的目的。

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

R_记忆犹新

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值