使用vue-quill-editor + element-ui +Django 重新修改图片的上传方式
比话不多说,上图:
由于原生的vue-quill-editor 在img标签上处理的不是很好
点击插入图片以后,会将图片改成base64或者字节流,插入文本当中,因此整个文本会显得很大,当进行上传的时候,mysql存储的text字段的最大长度是65535,可能会因为文本超过域值,而报错,因此需要改写vue-quill-editor 的上传文件方法。
前端的vue组件如下:
html部分
<template>
<div class="wirte">
<!-- # 标题 -->
<div class="tabbar" style="{background: white; }">
<span>小小笔记本</span>
<div class="right_wrapper">
<router-link class="selection" to="/"><i class="el-icon-s-promotion "></i>首页</router-link>
<div class="selection img_wrapper">
<img class="head_img selection" :src="imgUrl" alt="">
{{ name }}
</div>
</div>
</div>
<div class="drop">
<!-- 文章标题 -->
<div class="_title">
<router-link style="margin-left: 20px;" to=""> 文章标题:</router-link>
<el-input
style="width: 400px; margin-left: 5px;"
type="text"
placeholder="请输入内容"
v-model="title"
maxlength="30"
show-word-limit
>
</el-input>
<button class="commit_button" type="primary" @click="commit_it">提交文章</button>
<span>
字数:{{ content.length }}</span>
</div>
<!-- 图片上传组件辅助-->
<el-upload
class="avatar-uploader"
:action="serverUrl"
name="img"
:headers="header"
:show-file-list="false"
:on-success="uploadSuccess"
:on-error="uploadError"
:before-upload="beforeUpload">
</el-upload>
<quill-editor
class="editor"
v-model="content"
ref="myQuillEditor"
:options="editorOption"
@blur="onEditorBlur($event)" @focus="onEditorFocus($event)"
@change="onEditorChange($event)">
</quill-editor>
</div>
</div>
</template>
script 部分:
<script>
import Cookies from 'js-cookie';
import ImageResizes from 'quill-image-resize-module'
Quill.register('modules/imageResize', ImageResizes)
export default {
name: 'write',
data() {
return {
title: '',
imgUrl: '',
name: '',
serverUrl: "http://127.0.0.1:8000/artical/addimage.htm", // 这里写你要上传的图片服务器地址
header: {},
quillUpdateImg: false, // 根据图片上传状态来确定是否显示loading动画,刚开始是false,不显示
content: "",
editorOption: {
theme: 'snow',
placeholder: '说点什么吧...',
modules: {
toolbar: {
handlers: {
image: function(value) {
if (value) {
// 触发input框选择图片文件
document.querySelector(".avatar-uploader input").click();
} else {
this.quill.format("image", false);
}
},
},
container: [
["bold", "italic", "underline", "strike"], // 加粗 斜体 下划线 删除线
["blockquote", "code-block"], // 引用 代码块
[{ header: 1 }, { header: 2 }], // 1、2 级标题
[{ list: "ordered" }, { list: "bullet" }], // 有序、无序列表
[{ script: "sub" }, { script: "super" }], // 上标/下标
[{ indent: "-1" }, { indent: "+1" }], // 缩进
// [{'direction': 'rtl'}], // 文本方向
[{ size: ["small", false, "large", "huge"] }], // 字体大小
[{ header: [1, 2, 3, 4, 5, 6, false] }], // 标题
[{ color: [] }, { background: [] }], // 字体颜色、字体背景颜色
[{ font: [] }], // 字体种类
[{ align: [] }], // 对齐方式
["clean"], // 清除文本格式
["link", "image", "video"] // 链接、图片、视频
],
},
imageResize: {
displayStyles: {
backgroundColor: "black",
border: "none",
color: "white",
},
modules: ["Resize", "DisplaySize", "Toolbar"],
},
},
}
}
},
created() {
// 获取头像
this.imgUrl= '';
this.getImgUrl();
},
methods: {
// 提交文章
commit_it() {
this.$message.error("提交了提交了");
},
onEditorBlur() {
//失去焦点事件
},
onEditorFocus() {
//获得焦点事件
},
onEditorChange() {
//内容改变事件
this.$emit("input", this.content);
},
// 富文本图片上传前
beforeUpload() {
// 显示loading动画
this.quillUpdateImg = true;
},
uploadSuccess(res, file) {
// res为图片服务器返回的数据
// 获取富文本组件实例
let quill = this.$refs.myQuillEditor.quill;
// 如果上传成功
if (res.code == 200) {
// 获取光标所在位置
let length = quill.getSelection().index;
// 插入图片 res.url为服务器返回的图片地址
quill.insertEmbed(length, "image", res.url);
// 调整光标到最后
quill.setSelection(length + 1);
} else {
this.$message.error("图片插入失败");
}
// loading动画消失
this.quillUpdateImg = false;
},
// 富文本图片上传失败
uploadError() {
// loading动画消失
this.quillUpdateImg = false;
this.$message.error("图片插入失败");
},
// 获取头像的地址
getImgUrl() {
var a = Cookies.get();
// 遍历cookie的值
for(let key in a){
// console.log(key);
if( a[key] === '1' ) {
this.not_Login = false;
this.name = key;
// console.log('name: ' + this.name);
break;
}
}
// 查找cookie中有没有url的链接
if( Cookies.get('img_url') ) {
this.imgUrl = Cookies.get('img_url');
return ;
}
},
}
};
</script>
css 部分:
<style scoped>
.editor {
line-height: normal !important;
height: 500px;
}
._title {
font-size: 16px;
display: flex;
/* justify-content: space-between; */
width: 100%;
height: 45px;
line-height: 45px;
background: #F2F2F2;
}
.commit_button {
height: 35px;
line-height: 35px;
width: 80px;
text-align: center;
background: #2E9AFE;
color: white;
border-radius: 5px;
border: 0px;
margin-top: 5px;
margin-left: 30px;
}
.right_wrapper {
display: flex;
width: 20%;
justify-content: space-evenly;
}
.img_wrapper {
margin-right: 20px;
}
*{
margin: 0;
padding: 0;
}
html{
width: 100%;
height: 100%;
}
.space_box {
width: 35%;
height: 550px;;
margin: 70px auto;
}
.index {
font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";
width:100%;
height: 100%;
position: absolute;
}
.drop {
padding-top: 50px;
}
.editor {
line-height: normal !important;
height: 800px;
}
.ql-snow .ql-tooltip[data-mode=link]::before {
content: "请输入链接地址:";
}
.ql-snow .ql-tooltip.ql-editing a.ql-action::after {
border-right: 0px;
content: '保存';
padding-right: 0px;
}
.ql-snow .ql-tooltip[data-mode=video]::before {
content: "请输入视频地址:";
}
.ql-snow .ql-picker.ql-size .ql-picker-label::before,
.ql-snow .ql-picker.ql-size .ql-picker-item::before {
content: '14px';
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value=small]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value=small]::before {
content: '10px';
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value=large]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value=large]::before {
content: '18px';
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value=huge]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value=huge]::before {
content: '32px';
}
.ql-snow .ql-picker.ql-header .ql-picker-label::before,
.ql-snow .ql-picker.ql-header .ql-picker-item::before {
content: '文本';
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="1"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="1"]::before {
content: '标题1';
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="2"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="2"]::before {
content: '标题2';
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="3"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="3"]::before {
content: '标题3';
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="4"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="4"]::before {
content: '标题4';
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="5"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="5"]::before {
content: '标题5';
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="6"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="6"]::before {
content: '标题6';
}
.ql-snow .ql-picker.ql-font .ql-picker-label::before,
.ql-snow .ql-picker.ql-font .ql-picker-item::before {
content: '标准字体';
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=serif]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=serif]::before {
content: '衬线字体';
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=monospace]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=monospace]::before {
content: '等宽字体';
}
</style>
此时vue-quill-editor 的上传文件功能已经被改写了,将img文件的内容改成 了服务器里的 url ,这样大大节省了文本的长度
此时写后端的接口,文件服务器使用fastdfs,将request文件中包含的 FIle文件接收,然后,改成字节流,进行存储。
接口如下:
import os
from PIL import Image
from io import BytesIO
from django.http import HttpResponse, JsonResponse
from django.views import View
from Blog_Server.settings.dev import FDFS_URL
from Blog_Server.utils.fdfs.fastdfs_client import FDFSStorage
class addImage(View):
def get(self, request):
return HttpResponse("this is the addImage")
def post(self, request):
# 接收参数
img = request.FILES.get('img') # 获取到的是file类型的文件
img_s = Image.open(img)
img_s = img_s.resize((2140, 1080))
img_byte = BytesIO()
img_s.save(img_byte, format='PNG') # format: PNG or JPEG
binary_content = img_byte.getvalue() # bytes
# 图片存入fdfs服务器
image_url = FDFSStorage()._save(binary_content, 'img')
print(FDFS_URL+image_url)
# 返回图片的存储地址
# return JsonResponse({'code': 200, 'url': 'http://192.168.231.129:8888/group1/M00/00/00/wKjngWEBWIqASLhnAACBldwVS0g.v2-04e'})
return JsonResponse({'code': 200, 'url': FDFS_URL+image_url})
这样就能将图片内容转成url存在富文本中了.
示例如下:
在这里插入图片描述:看字体数!!!
解决报错
在build文件夹下的webpack.base.conf.js新增如下代码:
const webpack = require('webpack');
module.exports = {
plugins: [
new webpack.ProvidePlugin({
'window.Quill': 'quill/dist/quill.js',
'Quill': 'quill/dist/quill.js'
})
]
}