前言
当你写博客上传图片时,一定会为自己服务器空间被过多占用心生烦恼,你肯定不想本来就捉襟见肘的空间被大量图片所占用.
大部分网站都会选择把静态资源单独放置于对象存储中单独管理,这样不仅提升了服务器空间利用率,也一定程度上提供了安全保证,更能提高网站访问速度!
当前网络上有很多配置方案,但是更多都是使用七牛云作为网站图床使用. 因为七牛云会提供新用户每月10G上传图片的免费空间,当然你也可以选择其他服务商提供的对象存储服务,但具体优惠情况还要自己探究.
本篇文章主要记录我自己写的博客网站后台使用mdeditor
编辑器配合七牛云完成图片上传的主要操作!
一. 配置mdeditor
安装配置
pip install django-mdeditor -i https://pypi.douban.com/simple
注册为应用
INSTALLED_APPS = [
...
'mdeditor',
]
在 settings 中添加媒体文件的路径配置:
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'
注意:django3中
X_FRAME_OPTIONS
默认为 deny.如果你使用的是django3要在settings
中添加X_FRAME_OPTIONS = 'SAMEORIGIN'
,否则会出现跨域问题,导致图片上传后无法预览等问题!
添加扩展url和媒体文件url
from django.conf.urls import include
from django.contrib import admin
from django.urls import path
urlpatterns = [
....
path('mdeditor/', include(('mdeditor.urls', 'mdeditor'), namespace='mdeditor')), # 配置编辑器路由
re_path(r'^media/(?P.*)$', serve, {'document_root': MEDIA_ROOT}), #添加上传文件路径
....
修改models.py里需要使用编辑器渲染的字段
body = MDTextField(verbose_name='文章内容')
迁移数据库并注册入admin中, 再次运行程序即可使用markdown编辑器
测试使用编辑器上传图片,观察图片是否可正常查看与预览,此处略
参考配置文档
二. 注册七牛云
注册没什么难度,只要按照要求即可顺利完成注册,七牛地址
记得实名认证!
创建存储空间
主要操作步骤:
进入七牛选择产品-->对象存储-->空间管理-->新建空间-->配置存储空间信息
-
选择对象存储
-
新建空间
-
配置空间信息
空间建议选择公开,后面传图片访问时不会报错!
使用七牛云SDK
要使用七牛云官方已给出完整的SDK
文档
参考文档
安装
pip install qiniu
新增settings关于七牛云的配置
Access_Key = '你的Access_Key '
Secret_Key = '你的Secret_Key'
QINIU_URL_DOMAIN = 'xxxx.com' # 首次注册七牛云的用户,官方会提供一个30天的测试域名使用
封装七牛上传图片函数
在项目中创建utils
目录,并创建qiniu.py
文件用于封装函数
# -*- coding: utf-8 -*-
# flake8: noqa
import datetime
from qiniu import Auth, put_file, etag, put_data
import qiniu.config
#需要填写你的 Access Key 和 Secret Key
from run.settings import Access_Key, Secret_Key, QINIU_URL_DOMAIN
access_key = Access_Key
secret_key = Secret_Key
qiniu_url_domain = QINIU_URL_DOMAIN
# 为了显示图片类型,传入mdeditor源码中类型参数
def storage(file_data, file_extension):
'''
上传图片到七牛
'''
#构建鉴权对象
q = Auth(access_key, secret_key)
#要上传的空间
bucket_name = 'wsmzao'
#上传后保存的文件名(借鉴mdeditor源码设置图片名称)
key = '%s.%s' % ('{0:%Y%m%d%H%M%S%f}'.format(datetime.datetime.now()),
file_extension)
#生成上传 Token,可以指定过期时间等
token = q.upload_token(bucket_name, key, 3600)
#要上传文件的本地路径
# localfile = './sync/bbb.jpg'
ret, info = put_data(token, key, file_data)
# 最终返回显示链接
if info.status_code == 200:
base_url = 'http://%s/%s' % (qiniu_url_domain, ret.get("key"))
return base_url
else:
raise Exception("上传七牛失败")
if __name__ == '__main__':
storage()
# 可通过本地图片测试上传
#if __name__ == '__main__':
# with open("本地上传图片.jpg", "rb") as f:
# file_data = f.read()
# storage(file_data)
先使用本地图片测试一下是否可正常传入七牛云,然后再做调整与修改
修改mdeditor上传函数
观察mdeditor
源码,对保存图片处使用刚刚封装的七牛函数做替换
# -*- coding:utf-8 -*-
import os
import datetime
from django.views import generic
from django.conf import settings
from django.http import JsonResponse
from django.views.decorators.csrf import csrf_exempt
from django.utils.decorators import method_decorator
from .configs import MDConfig
from django.views.decorators.clickjacking import xframe_options_exempt, xframe_options_sameorigin
from django.views.decorators.csrf import csrf_exempt
from utils.qiniu import storage
# TODO 此处获取default配置,当用户设置了其他配置时,此处无效,需要进一步完善
MDEDITOR_CONFIGS = MDConfig('default')
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)
# 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('.')
# list.pop(-1)表示列表最后一个值
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': ""
})
# save image
file_data = upload_image.read()
# 调用七牛云上传
base_url = storage(file_data, file_extension)
return JsonResponse({'success': 1,
'message': "上传成功!",
'url': base_url
})
最终效果展示:
如果你有自己的域名,建议直接改为自己的域名,这对于你应该没有什么难度!