当前位置: 首页 > 工具软件 > mdEditor > 使用案例 >

django-mdeditor整合腾讯COS,实现上传图片到腾讯云

方飞翼
2023-12-01

大厂的对象存储都提供了完善的SDK,使用非常简单。django使用对象存储有两种场景,一种结合django的Storage存储类,图片经由模型上传至COS,然后由django端删除,本地不保留;另外一种自定义场景,比如结合django-mdeditor使用。本文介绍的是第二种,结合django-mdeditor编辑器,通过“添加图片”直接上传到腾讯COS中。

腾讯COSpython文档地址:https://cloud.tencent.com/document/product/436/12269
未来一段时间内将会一直研究django场景下使用腾讯COS的用法。腾讯COS提供了对象的上传、下载、查看对象列表、初始化客户端、创建桶、查看桶列表等众多接口,本文着重学习对象的上传。

实现整合的关键点
了解django-mdeditor的工作流程
django-mdeditor默认上传图片到本地,在选中图片后就会完成上传并返回相对路径到编辑器,编辑器和后端使用json通信。编辑器工作的js文件为site-packages/mdeditor/static/mdeditor/js/plugins/image-dialog/image-dialog.js,python文件为site-packages/mdeditor/views.py。大约流程为:

1、渲染图片上传form

该form由image-dialog.js渲染,action的值为/mdeditor/uploads/?guid=1639898526591,guid是渲染时的时间戳,暂时不清楚用来干啥,在view中看不到利用这个参数的利用。

2、编辑器的urls.py

uploads相关的请求均交由这个路由,并调用views.py中的UploadView接收图片,保存后返回路径给编辑器

3、views.py的UploadView

class UploadView(generic.View):  
    """ upload image file """  

    @method_decorator(csrf_exempt)  
    def dispatch(self, *args, **kwargs):  
        return super(UploadView, self).dispatch(*args, **kwargs)  

    def post(self, request, *args, **kwargs):  
        upload_image = request.FILES.get("editormd-image-file", None)  
        print('upload:', upload_image)  
        media_root = settings.MEDIA_ROOT  

        # image none check  
        if not upload_image:  
            return JsonResponse({  
                'success': 0,  
                'message': "未获取到要上传的图片",  
                'url': ""  
            })  

        # image format check  
        file_name_list = upload_image.name.split('.')  
        file_extension = file_name_list.pop(-1)  
        file_name = '.'.join(file_name_list)  
        if file_extension not in MDEDITOR_CONFIGS['upload_image_formats']:  
            return JsonResponse({  
                'success': 0,  
                'message': "上传图片格式错误,允许上传图片格式为:%s" % ','.join(  
                    MDEDITOR_CONFIGS['upload_image_formats']),  
                'url': ""  
            })  

        # image floder check  
        file_path = os.path.join(media_root, MDEDITOR_CONFIGS['image_folder'])  
        print('上传路径:', file_path)  
        if not os.path.exists(file_path):  
            try:  
                os.makedirs(file_path)  
            except Exception as err:  
                return JsonResponse({  
                    'success': 0,  
                    'message': "上传失败:%s" % str(err),  
                    'url': ""  
                })  

        # save image  
        file_full_name = '%s_%s.%s' % (file_name,  
                                       '{0:%Y%m%d%H%M%S%f}'.format(datetime.datetime.now()),  
                                       file_extension)  
        with open(os.path.join(file_path, file_full_name), 'wb+') as file:  
            for chunk in upload_image.chunks():  
                file.write(chunk)  

        return JsonResponse({'success': 1,  
                             'message': "上传成功!",  
                             'url': os.path.join(settings.MEDIA_URL,  
                                                 MDEDITOR_CONFIGS['image_folder'],  
                                                 file_full_name)})  

编辑器部分相对容易理解,不过要修改编辑器界面的内容,就有点麻烦了,自定义工具栏可以通过设置来实现,但要调整其他就有点难度了,因为作者封装得太好了,压根看不懂js文件。

了解腾讯COS的接口和使用方法
腾讯COS文档齐全,用心读一读练一练就会了。COS工作的流程为:下载SDK,初始化COS客户端 => 配置好腾讯id、密码和存储桶id => 选择文件 => 携带必要参数(如上传后的图片命名和后缀,这个由参数key控制) => 读取图片的url。整个过程文档有详细的示例代码。

整合的思路
模仿编辑器的UploadView,写一个新的view,把保存图片到本地这部分改为上传到腾讯COS。

实现代码
在编辑器的view中写一个COS的类
该类实现客户端初始化、上传和读取url。不过,为了规范点,先在setting文件中配置一下COS的基础信息。

安装COS的SDK

pip install -U cos-python-sdk-v5
from qcloud_cos import CosConfig
from qcloud_cos import CosS3Client
import sys
import logging

TENCENT_COS = {  
    'secret_id': '腾讯云的id',  
    'secret_key': '腾讯云的密钥',  
    'bucket': '存储桶id',  
    'region': '桶的区域',  
}  

以上这些信息需要到腾讯云中能找得到。
COS类写在了编辑器的类中:


class TencentCOS:  

    def __init__(self):  
        self.secret_id = settings.TENCENT_COS['secret_id']  
        self.secret_key = settings.TENCENT_COS['secret_key']  
        self.bucket = settings.TENCENT_COS['bucket']  
        self.region = settings.TENCENT_COS['region']  
        self.token = None  
        self.scheme = 'https'  

    #初始化客户端  
    def client(self):  
        logging.basicConfig(level=logging.INFO, stream=sys.stdout)  
        config = CosConfig(  
                            Region=self.region,  
                            SecretId=self.secret_id,  
                            SecretKey=self.secret_key,  
                            Token=self.token,  
                            Scheme=self.scheme  
                        )  
        return CosS3Client(config) #返回一个初始化的客户端,后续操作都需要基于这个客户端实例  

    # 获取对象url  
    def get_obj_url(self, bucket, key):  
        return self.client().get_object_url(bucket, key)  

    #上传文件,返回上传后的url  
    def upload_cos(self, image, key):  
        with open(image, 'rb') as fp:  
            response = self.client().put_object(  
                Bucket = self.bucket,  
                Body = fp,  
                Key = key,   #key是保存在cos时的名称  
                StorageClass = 'STANDARD',  
                EnableMD5 = False  
                )  
        return self.get_obj_url(self.bucket, key)  

1、在upload_cos方法中,参数image是要上传图片的路径,使用绝对路径上传,参数key是上传到COS后保存的名称,需要文件名+后缀,本地的图片名称可能是中文,需要自己重新组织key,等于图片重命名,然后传参给upload_cos,COS将会使用key来保存这个图片。

2、get_obj_url方法用来获取上传后图片的url,有网友按照COS的链接规律自己组织了url,这也是可以的。

  • 自己实现一个view

后半部分的代码,可浏览我个人博客http://www.nodepro.cn/nodes/node/5

 类似资料: