python操作小程序云存储进行文件上传下载,实现文件上传重复校验


最近开发了一个进行源码展示的小程序。每次新增一个项目信息都会展示项目效果的演示图。因此在新增数据之前,需要把演示图先上传到云存储。基于此通过python实现文件的上传。

1、获取access_token

获取access_token可以参看上篇文章

2、文件上传api

文件上传的api需要分两步调用
第一次请求"获取上传链接"接口https://api.weixin.qq.com/tcb/uploadfile?access_token=ACCESS_TOKEN,post参数为云开发环境id env以及云存储的目标路径path。从该接口的返回值中得到上传url以及相关的上传密钥,再进行文件流的上传。

2.1 获取上传/下载链接

class Cloud:
    def __init__(self, env, collection_name):
        self.access_token = get_access_token()
        self.add_url = f'https://api.weixin.qq.com/tcb/databaseadd?access_token={
      
      self.access_token}'
        self.upload_url = f'https://api.weixin.qq.com/tcb/uploadfile?access_token={
      
      self.access_token}'
        self.download_url = f'https://api.weixin.qq.com/tcb/batchdownloadfile?access_token={
      
      self.access_token}'
        self.env = env
        self.collection_name = collection_name
        self.post_data = {
    
    "env": self.env}  # 请求参数,每次的请求参数需要env环境id和query查询语句

    def upload(self, file_name):
        post_data = {
    
    "env": self.env, "path": file_name}
        res = requests.post(self.upload_url, data=json.dumps(post_data))
        return res.json()

    def download(self, file_id, max_age=7200):
        post_data = {
    
    "env": self.env, "file_list": [{
    
    "fileid": file_id, "max_age": max_age}]}
        res = requests.post(self.download_url, data=json.dumps(post_data))
        return res.json()
        
    def add(self, new_data):
        """
        new_data: list of dict
        """
        new_data = "{data:%s}" % new_data
        self.post_data["query"] = f"db.collection('{
      
      self.collection_name}').add({
      
      new_data})"
        response = requests.post(self.add_url, data=json.dumps(self.post_data))
        result = response.json()
        # 执行成功返回状态码0
        if result["errcode"] == 0:
            return result['id_list']

2.2根据上传参数的返回值进行文件流上传

这里我们看下拿到上传链接后的返回是怎样的。这里官方文档给出了具体数据规范
在这里插入图片描述
需要注意的是上传的请求格式为multipart/form-data。一个上传文件的完整流程可以通过如下函数实现。
在获取上传链接后,将该链接代入到下载链接中,获取返回值,判断文件不存在时再上传,否则中断上传操作。

def upload_file(img_path, env, collection_name):
    """
    img_path:本地图片/文件路径
    """
    cloud = Cloud(env, collection_name)
    # 需要上传的云存储文件夹名称
    cloud_dir_name = "."
    # 第一次请求获取上传连接
    upload_path = f"{
      
      cloud_dir_name}/{
      
      img_path}"
    res = cloud.upload(upload_path)
    file_id = res['file_id']
    # 从上传链接中获取file_id检查该文件是否存在
    check_exisit = cloud.download(file_id)
    # 调用下载链接确认文件不存在再上传
    if check_exisit["errcode"] == 0 and check_exisit["file_list"][0]["status"] == 1:
        # 拿到上传连接后获取密钥,读取本地文件流上传
        if res["errcode"] == 0:
            post_data = {
    
    
                "key": upload_path,
                "Signature": res["authorization"],
                "x-cos-security-token": res["token"],
                "x-cos-meta-fileid": res["cos_file_id"],
                "file": open(img_path, "rb")
            }
            url = res["url"]
            body = MultipartEncoder(
                fields=post_data,
                boundary=''.join(random.sample(string.ascii_letters + string.digits, 30))
            )
            headers = {
    
    "Content-Type": body.content_type}
            upload_res = requests.post(url, data=body, headers=headers)
            if upload_res.status_code!=204:
                print(upload_res.content)
                import sys
                sys.exit(0)
    else:
        print(f"{
      
      cloud_dir_name}文件已存在,直接读取")
    # 文件上传完成后加入数据库
    item["img_path"] = file_id
    res = cloud.add(item)
    print(res)

最终界面数据的展示效果可以通过小程序查看

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/Demonslzh/article/details/125760628