Vue Element UI 之富文本图片上传服务器 + 图片地址插入富文本

该案例的情况

  • vue版本:vue cli3
  • 插件:vue-quill-editor
  • vue-quill-editor的增强模块:quill-image-extend-module

quill-image-extend-module功能:

  • 提供图片上传到服务器的功能
  • 复制插入
  • 显示上传进度
  • 显示上传成功或者失败

文章目录

      • 一、选择这种方式的来龙去脉(读者可自行跳过)
      • 二、实现
          • 2.1 安装插件
          • 2.2 引入
          • 2.3 使用
            • 2.3.1 方法一(推荐)
            • 2.3.2 方法一延申:不改写方法
            • 2.3.3 方法三(不推荐)

一、选择这种方式的来龙去脉(读者可自行跳过)

本意呢,是打算将整个富文本的数据都上传到阿里云服务器上,但是把 Quill 数据封装进 fromData 中上传时,总是报错,报错信息是 Required request part 'file' is not present,如下
Vue Element UI 之富文本图片上传服务器 + 图片地址插入富文本_第1张图片
这个问题应该是前端传参和后台接收参数不一致的问题,和我的后台协商之后,发现并没有什么不妥之处,因为通过 el-upload 上传图片也是通过 formData 数据,是可以成功上传的。研究考虑一番之后,决定放弃此方式,改用存储数据库来实现,将富文本中插入的图片上传服务器、富文本的 html 字符串存储数据库。之所以将图片上传服务器,还有另一个原因,就是如果直接将富文本的 html 字符串存储数据库的话,富文本中插入的图片会以 base64 格式存储,占空间太大;而将图片上传服务器,把返回的图片地址以 存入富文本的 html 字符串中,可以大大缩小空间。下面上两张图对比一下

base64 格式:(截图没有截下全部,大概31kb)
Vue Element UI 之富文本图片上传服务器 + 图片地址插入富文本_第2张图片
图片地址格式:
Vue Element UI 之富文本图片上传服务器 + 图片地址插入富文本_第3张图片

二、实现

好了,来龙去脉记录完毕,下面开始说说如何实现

2.1 安装插件
npm install vue-quill-editor --save-dev
npm install quill-image-extend-module --save-dev

注:在下面的使用过程中,如果出现 modules 里面缺少相关依赖,直接在项目中执行 npm install,就可以

2.2 引入
import { quillEditor, Quill } from 'vue-quill-editor'
import { container, ImageExtend, QuillWatch } from 'quill-image-extend-module'
Quill.register('modules/ImageExtend', ImageExtend)
2.3 使用

由于是第一次做这个功能,百度了很多,测试了两种方法。下面对这两种方法进行分析

2.3.1 方法一(推荐)
  • 实现思路:使用 quill-editor,通过改写 ImageExtend,进行图片上传、 img 标签改写(将图片地址插入 img 标签)
  • 效果:可以实现图片上传服务器、图片地址以 src 方式插入 img 标签并回显在 quill 编辑器内容中
<template>
	<div class="testuploadquillpicandback">
		<quill-editor @change="onEditorChange($event)"
		 	id="desc" ref="quill" v-model="desc" :options="editorOption">
		</quill-editor>
	</div>
</template>

<script>
	import { quillEditor, Quill } from 'vue-quill-editor'
	import { container, ImageExtend, QuillWatch } from 'quill-image-extend-module'
	Quill.register('modules/ImageExtend', ImageExtend)
	
	export default{
		data() {
			return {
				desc: '',
				editorOption: {
					placeholder: '此处输入赛事规程',
					modules: {
						ImageExtend: {
							loading: true,
							name: 'file',//图片参数名
							size: 1, // 可选参数 图片大小,单位为M,1M = 1024kb
							action: '/feelings/common/upload/file',//上传的服务器地址,如果action为空,则采用base64插入图片
							// response 为一个函数,用来获取服务器返回的具体图片地址
							response: res => {
								console.log(res)
								const imgUrl = 'http://' + res.data
								return imgUrl
							},
							headers: xhr => {
								// 上传图片请求需要携带token的 在xhr.setRequestHeader中设置,这里我的token存放在sessionStorage中
								xhr.setRequestHeader("token", window.sessionStorage.getItem('token'))
							},
							// 可选参数 设置请求头部
							sizeError: () => {}, // 图片超过大小的回调
							start: () => {}, // 可选参数 自定义开始上传触发事件
							end: () => {}, // 可选参数 自定义上传结束触发的事件,无论成功或者失败
							error: () => {}, // 可选参数 上传失败触发的事件
							success: () => {
								console.log('ImageExtend中的success:上传成功')
							}, // 可选参数  上传成功触发的事件
							change: (xhr, formData) => {
								// xhr.setRequestHeader('myHeader','myValue')
								// formData.append('token', 'myToken')
							} // 可选参数 每次选择图片触发,也可用来设置头部,但比headers多了一个参数,可设置formData
						},
						// 如果不上传图片到服务器,此处不必配置
						toolbar: {
							// container为工具栏,此次引入了全部工具栏,也可自行配置
							container: [
								["bold", "italic", "underline", "strike"],
								["blockquote", "code-block"],
								[{ header: 1 }, { header: 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: [] }],
								["image"]
							],
							// 上传成功,回显图片(会进入如上面ImageExtend的各过程,返回
							handlers: {
								image: function() {
									// 劫持原来的图片点击按钮事件
									QuillWatch.emit(this.quill.id)
								}
							}
						}
					}
				},
			}
		},
		methods: {
			// quill的change事件
			onEditorChange(e) {
				console.log('onEditorChange打印e')
				console.log(e)
			}
		}
	}
</script>

参考自:https://www.cnblogs.com/dachengzizi/p/11805488.html

2.3.2 方法一延申:不改写方法
  • 实现思路:使用 quill-editor,不改写方法
  • 效果:可以实现图片上传,但是返回图片地址为 base64 格式
<template>
	<div class="testuploadquillpicandback">
		<quill-editor @change="onEditorChange($event)"
		 id="desc" ref="quill" v-model="desc">
		</quill-editor>
	</div>
</template>

<script>
	import { quillEditor, Quill } from 'vue-quill-editor'
	import { container, ImageExtend, QuillWatch } from 'quill-image-extend-module'
	Quill.register('modules/ImageExtend', ImageExtend)
	
	export default{
		data() {
			return {
				desc: ''
			}
		},
		methods: {
			// quill的change事件
			onEditorChange(e) {
				console.log('onEditorChange打印e')
				console.log(e)
			}
		}
	}
</script>

<style>
</style>

Vue Element UI 之富文本图片上传服务器 + 图片地址插入富文本_第4张图片

参考自:https://www.cnblogs.com/bingchenzhilu/p/11951571.html

2.3.3 方法三(不推荐)
  • 实现思路:使用 quill-editor 和 input,重写 ImageExtend,并通过 input 的 change 事件进行上传
  • 效果:可以实现图片上传,但是图片地址插入 quill 内较麻烦(我没有尝试去做这个,因为上面方法已经可以满足我的需求,而且更方面管理)
<template>
	<div class="testuploadquillpicandback">
		<quill-editor @change="onEditorChange($event)"
		 id="desc" ref="quill" v-model="desc" :options="editorOption">
		</quill-editor>
		// 实际使用时,可以隐藏以得到更好的体验
		<input type="file" @change="change" id="upload" />
	</div>
</template>

<script>
	import { quillEditor, Quill } from 'vue-quill-editor'
	import { container, ImageExtend, QuillWatch } from 'quill-image-extend-module'
	Quill.register('modules/ImageExtend', ImageExtend)
	
	export default{
		data() {
			return {
				desc: '',
				editorOption: {
					placeholder: '此处输入赛事规程',
					modules: {
						ImageExtend: {
							loading: true,
							name: 'file',//图片参数名
							size: 1, // 可选参数 图片大小,单位为M,1M = 1024kb
							action: '/feelings/common/upload/file',//上传的服务器地址,如果action为空,则采用base64插入图片
							// response 为一个函数,用来获取服务器返回的具体图片地址
							response: res => {
								console.log('ImageExtend中的response')
								console.log(res)
								const imgUrl = 'http://' + res.data
								return imgUrl
							},// 注意:原作者中的res.data和我的不一样,我的res.data=图片地址
							headers: xhr => {
								// 上传图片请求需要携带token的 在xhr.setRequestHeader中设置
								xhr.setRequestHeader("token", window.sessionStorage.getItem('token'))
							},
							// 可选参数 设置请求头部
							sizeError: () => {}, // 图片超过大小的回调
							start: () => {}, // 可选参数 自定义开始上传触发事件
							end: () => {}, // 可选参数 自定义上传结束触发的事件,无论成功或者失败
							error: () => {}, // 可选参数 上传失败触发的事件
							success: () => {
								console.log('ImageExtend中的success:上传成功')
							}, // 可选参数  上传成功触发的事件
							change: (xhr, formData) => {} // 可选参数 每次选择图片触发,也可用来设置头部,但比headers多了一个参数,可设置formData
						},
						// 如果不上传图片到服务器,此处不必配置
						toolbar: {
							// container为工具栏,此次引入了全部工具栏,也可自行配置
							container: [
								["bold", "italic", "underline", "strike"],
								["blockquote", "code-block"],
								[{ header: 1 }, { header: 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: [] }],
								["image"]
							],
							// 进入input的change事件,可以实现上传,但是不能把返回的图片地址插入到quill内容中
							handlers: {
								image: function(value) {
									if (value) {
										// 劫持原来的图片点击按钮事件,#upload即为自己写的上传,可以使用最简单的input
										document.querySelector('#upload').click()
									} else {
										this.quill.format('image', false)
									}
								}
							}
						}
					}
				},
			}
		},
		methods: {
			// quill的change事件
			onEditorChange(e) {
				console.log('onEditorChange打印e')
				console.log(e)
			},
			// input的change事件:可以实现上传,但是不能把返回的图片地址插入到quill内容中
			async change(e) {
				console.log('input的change事件')
				let file = e.target.files[0]
				const formData = new FormData()
				formData.append('file', file)
				// 下面可以根据后端写的上传接口进行传递参数
				const { data: res } = await this.$http.post('/feelings/common/upload/file', formData)
				console.log(res)
				if (res.code !== 200) {
					this.$message.error('上传失败')
				}
				this.$message.success('上传成功')
			}
		}
	}
</script>

<style>
</style>

Vue Element UI 之富文本图片上传服务器 + 图片地址插入富文本_第5张图片
好了,到此为止,两种方式测试完毕,读者可根据自己的需求写适合自己的组件

你可能感兴趣的:(#,element,vue)