前文
今天做一个后台管理页面的时候,要用到一个文本编辑器,视频教程上使用的是富文本编辑器Tinymce,但是Tinymce是一个传统javascript插件,默认不能用于Vue.js因此需要做一些特殊的整合步骤,步骤有些许麻烦,于是打算用跟此博客一样,用markdown带代替,因为此blog的markdown中上传图片是自己修改方法,上传到oss中的,此时传入数据库的图片路径就是保存的到云存储里面的路径。
而我发现Tinymce编辑器在做原本的添加图片时,Tinymce中的图片上传功能直接存储的是图片的base64编码,因此无需图片服务器。
所以,突发奇想能不能修改markdown添加图片功能,实现将图片转为Base64,存入数据库,查找了相关资料后,发现这样虽然可以,但是会导致Pandoc编译速度慢,甚至内存堆栈不足,虽然不推荐此使用,但是还是尝试一下。
正文
1、首先引入markdwon
npm install mavon-editor --save
2、在main.js中注册编辑器组件
import mavonEditor from 'mavon-editor'
import 'mavon-editor/dist/css/index.css'
Vue.use(mavonEditor);
3、集成到vue组件中,注册组件
import { mavonEditor } from 'mavon-editor'
import 'mavon-editor/dist/css/index.css';
============================================
compents{
mavonEditor
}
<mavon-editor ref="md" v-model="courseInfo.description" @imgAdd="handleEditorImgAdd" />
4、编写添加图片方法
imgAdd()方法是Base64方式,
handleEditorImgAdd()方法就是传统的将图片上传到服务器方法
注意这里我是封装的axios异步请求,引入了courseApi,不是用的原生的axios请求方式,修改即可
//Base64添加图片(不推荐)
imgAdd(pos, $file) {
// console.log("开始上传图片 ", $file);
// console.log("formate4 " + $file.miniurl);
this.imgParams.imgName = $file.name;
this.imgParams.formData = $file.miniurl;
courseApi.imgAdd(this.imgParams).then((response) => {
console.log(response.data.base64);
if (response.success == true) {
let url = response.data.base64;
this.$refs.md.$img2Url(pos, url);
} else {
alert("error");
}
});
},
handleEditorImgAdd(pos, file) {
console.log("pos:" + pos);
// 第一步.将图片上传到服务器.
var formdata = new FormData();
formdata.append("file", file);
courseApi.ossImgAdd(formdata).then((response) => {
// 第二步.将返回的url替换到文本原位置
var url = response.data.url;
//通过引入对象获取: import {mavonEditor} from ... 等方式引入后,此时$vm即为mavonEditor
//通过$refs获取: html声明ref : <mavon-editor ref=md ></mavon-editor>, 此时$vm为 this.$refs.md`
this.$refs.md.$img2Url(pos, url);
});
},
两个方法对应的api
//此路径为把markdown上传的照片保存为Base64
imgAdd(imgParams) {
return request({
url: `/eduService/course/markdownImgUpload`,
method: "post",
data: imgParams
});
},
ossImgAdd(file) {
return request({
url: `ossService/file`,
method: "post",
data: file
});
}
这里主要说用Base64传输的方式,
这里其实后端接口多余了,我是想把前端上传的图片保存到本地,试一下base64解码为二进制转化为图片的过程,单纯为了好玩。
可以跳过后端部分,直接修改前端 imgAdd()方法为下面一行即可,直接赋值就行,可以直接跳过第5步,看第6步。
this.$refs.md.$img2Url(pos, $file.miniurl);
5、后端接口
ImgParams 里面封装两个string对象,imgName formData接收数据
//把markdown上传的图片转化为Base64,解码为二进制,再将二进制转化为图片并保存到本地指定路径。
@PostMapping("markdownImgUpload")
public Result markdownImgUpload(@RequestBody ImgParams imgParams){
System.out.println("requestBody: "+imgParams);
String imgBase64=imgParams.getFormData();//拿到base64
String imgName=imgParams.getImgName();//拿到图片名字
// 将base64的前端识别信息,给去除
String noHeaderBase64 = MyUtils.removeTheHead(imgBase64);
System.out.println(noHeaderBase64);
BASE64Decoder decoder = new BASE64Decoder();
if (noHeaderBase64==null){
return Result.error();
}else {
//Base64解码为图片
try {
byte[] b = decoder.decodeBuffer(noHeaderBase64);
// b = decoder.decodeBuffer(imgBase64);
for(int i=0;i<b.length;++i)
{
if(b[i]<0)
{
//调整异常数据z
b[i]+=256;
}
}
String path="D:\\base64\\";
//新生成的图片
String imgFilePath = path+imgName;
OutputStream out = new FileOutputStream(imgFilePath);
out.write(b);
out.flush();
out.close();
// System.out.println("adf "+out.toString());
} catch (IOException e) {
e.printStackTrace();
}
}
return Result.ok().data("base64",imgBase64);
}
请求体如下:
可以看到,formData中封装的就是base64编码,这里有个小坑就是base64前23个字符是给前端用来做识别的所以我们后台这边如果要转成图片就需要把它前23个字符去掉,不然图片打开会显示无法识别,也就是转图片失败。封装了一个MyUtils.removeTheHead(imgBase64)工具类,用于去除前23位字符。
public static String removeTheHead(String base64) {
for (int i = 0; i < base64.length(); i++) {
if (base64.charAt(i) == ',') {
base64 = base64.substring(i + 1);
break;
}
}
return base64;
}
这里我将Base64解码转化为二进制,再将二进制转化为图片保存到本地路径。
最终返回imgBase64(也就是前端传过来的参数$file.miniurl; )
6、完成添加图片
可以看到此时实现了markdown以Base64编码的形式添加图片
但是这样的弊端相信大家很容易看出来,就是它的编码太长了,图片只截取了上面一部分,下面还有很长很长,严重影响编辑文本时的体验。
大家可以对比一下,下面是以第二种方式上传到服务器,里面是封装的是图片的链接,可以直接打开。是不是简洁很多,这里我的文件路径还是我后端封装了uuid加日期之后的路径,要是不封装路径更简洁,一行就可以显示完。
7、保存数据到数据库
第一种是将图片以Base64编码的形式存入数据库,注意用Base64编码时,数据库字段会很长。
第二种是将图片的链接路径存入数据库。
下面是Base64形式,实在太长了,我就不往后拉展示了,理解就行。
8、如果没有oss存储服务器,或者就想用Base编码形式保存图片,怎样进行文档编辑呢?
首先把需要内嵌的图片做成base64形式的字符,然后用类似下列形式放置文件尾:
[fire]:data:image/jpeg;base64,UklGRhgpAABXRUJQVlA4IAwpAACQOgGdASr0AfQBPpFEnUqlo6+uJzF6KfASCWduvmgJ9X0GriPlq1LUkV1yD+Nno7itmvLEd4f7dxskab1CXD3Rv
然后markdown中引用id:
![文本展示内容][fire]
效果展示:
这样就可以实现将图片以Base64编码的形式插入到markdowm中了。