TOP

Django models.FileField 信息上传至腾讯云 COS 存储桶

准备工作

去腾讯云上申请个存储桶, 记得权限里面打开公有读, 否则链接无法打开吗会提示访问权限被拒绝

然后准备cos 外部对接的凭证注意自己的存储桶的name 和 region 等下都要用到

 

 

代码

配置准备好这些

COS_SECRET_ID = "..."
COS_SECRET_KEY = "..."
REGION = "..."
BUCKET = "..."

 

写一个存储类

import random
import time
from hashlib import sha1

from django.conf import settings
from django.core.files.storage import Storage
from django.utils.deconstruct import deconstructible
from qcloud_cos import CosConfig, CosS3Client

secret_id = settings.COS_SECRET_ID
secret_key = settings.COS_SECRET_KEY
region = settings.REGION
bucket = settings.BUCKET
config = CosConfig(Region=region,
                   Secret_id=settings.COS_SECRET_ID,
                   Secret_key=settings.COS_SECRET_KEY)
client = CosS3Client(config)
host = 'https://' + bucket + '.cos.' + region + '.myqcloud.com/'


@deconstructible
class CosStorage(Storage):
    def save(self, name, content, max_length=None):
        suffix = name.split('.')[-1]
        key = self.generate_key(suffix)
        try:
            client.put_object(
                Bucket=bucket,
                Body=content.read(),
                Key=key,
                EnableMD5=False
            )
        except Exception as e:
            raise
        return host + key

    def generate_key(self, suffix):
        random_str = ''.join([str(random.randint(1, 9)) for i in range(3)])
        file_name = str(int(time.time() * 10000000)) + random_str
        s = sha1()
        s.update(file_name.encode('utf-8'))
        file_name = str(s.hexdigest())
        key = f"{file_name}.{suffix}"
        return key

    def url(self, name):
        return name

models.py 中的设定 storge 为自定义的 cos存储类

    icon_file = models.FileField(verbose_name='头像文件', storage=CosStorage(),
                                 null=True, blank=True, max_length=256)

 

效果

在admin 中可以看到文件的连接, 上传保存后的文件会自动保存在 cos 对应的 存储桶中

 

访问链接后可以打开图片即可

 

其他

到此已经实现了需求, 但是仍然存在一个问题, 上传上去的图片永远无法删除

因为不论是修改还是创建都是一样的走 save 逻辑上传

期望的修改逻辑应该是将原有的文件在桶中清除

再存储类中无法实现此操作, 因此需要在序列化中重写 update 方法即可

不论是修改还是清空都可以对原有的数据进行清除

    def update(self, instance, validated_data):
        icon_file_url = instance.icon_file.name
        # 如果存在更新文件, 删除老的文件
        if "icon_file" in validated_data and icon_file_url:
            res = cos_client.delete_object(
                Bucket=bucket,
                Key=icon_file_url.split(host)[1]
            )return super().update(instance, validated_data)

 

posted @ 2022-07-14 16:18  羊驼之歌  阅读(183)  评论(0编辑  收藏  举报