本文只介绍解决思路,不提供具体上传本地图片的前后端功能实现,因为这部分网上已经有很多了
一.背景
最近在做个人博客网站的博客编辑部分,原本使用的是Summernote富文本编辑器,不过这个编辑器的文本格式是html的,拓展性没那么好,所以改用Markdown格式的编辑器:Bootstrap Markdown编辑器
但是Bootstrap Markdown有个问题:插入图片默认只允许输入图片URL,无法上传本地文件
这就有点难搞了,网上相关的资料又很少,没办法,只能自己看官方文档了。
这个是在线文档(可能需要科学上网):http://www.taufanaditya.com/bootstrap-markdown/
这个是Github上的,可以下载下来看:https://github.com/westhack/Bootstrap-Markdown
二.查阅文档,看看有没有重写插入图片回调函数的方法
1.文档中有提到图片上传可以集成 dropzone,但是我试了一下不管用,可能是版本问题,总之我没用这个方法。
2.文档中有这样一行话:
Events/Hook
There are six main events within Bootstrap-Markdown lifecycle : onShow, onPreview, onChange, onSave, onFocus and onBlur. Heres an example to hook into those events via
大意就是可以设置这几个功能的触发函数,但只有这六个,没有插入图片的触发函数,作罢。
3.添加自定义按钮,这个功能确实是满足了我们的需求,而且使用起来很简单。但我没有用这个方法,因为我想直接修改它的原生按钮。
如果要通过添加自定义按钮来完成,直接定义callback回调函数为我们自己需要的上传图片的功能函数就行了。
下面是文档中的示例代码:
$("#target-editor-with-custom-buttons").markdown({
additionalButtons: [
[{
name: "groupCustom",
data: [{
name: "cmdBeer",
toggle: true, // this param only take effect if you load bootstrap.js
title: "Beer",
icon: "glyphicon glyphicon-glass",
callback: function(e){
// Replace selection with some drinks
var chunk, cursor,
selected = e.getSelection(), content = e.getContent(),
drinks = ["Heinekken", "Budweiser",
"Iron City", "Amstel Light",
"Red Stripe", "Smithwicks",
"Westvleteren", "Sierra Nevada",
"Guinness", "Corona", "Calsberg"],
index = Math.floor((Math.random()*10)+1)
// Give random drink
chunk = drinks[index]
// transform selection and set the cursor into chunked text
e.replaceSelection(chunk)
cursor = selected.start
// Set the cursor
e.setSelection(cursor,cursor+chunk.length)
}
}]
}]
]
})
三.重写JS文件
既然文档没有提供重写插入图片回调函数的功能,那就只能自己改js文件了。
打开bootstrap-markdown.js,搜索cmdImage,cmdImage就是原生的插入图片按钮的名字,找到代码如下:
{
name: 'cmdImage',
title: 'Image',
hotkey: 'Ctrl+G',
icon: { glyph: 'glyphicon glyphicon-picture', fa: 'fa fa-picture-o', 'fa-3': 'icon-picture' },
callback: function(e){
// Give ![] surround the selection and prepend the image link
var chunk, cursor, selected = e.getSelection(), content = e.getContent(), link;
if (selected.length === 0) {
// Give extra word
chunk = e.__localize('enter image description here');
} else {
chunk = selected.text;
}
link = prompt(e.__localize('Insert Image Hyperlink'),'http://');
var urlRegex = new RegExp('^((http|https)://|(//))[a-z0-9]', 'i');
if (link !== null && link !== '' && link !== 'http://' && urlRegex.test(link)) {
var sanitizedLink = $('<div>'+link+'</div>').text();
// transform selection and set the cursor into chunked text
e.replaceSelection('!['+chunk+']('+sanitizedLink+' "'+e.__localize('enter image title here')+'")');
cursor = selected.start+2;
// Set the next tab
e.setNextTab(e.__localize('enter image title here'));
// Set the cursor
e.setSelection(cursor,cursor+chunk.length);
}
}
}]
}
callback里的代码就是回调函数了,这一块的代码就是读取弹出窗口中用户输入的URL存到 link中,然后进行正则表达式判断,如果判断通过就插入到编辑框内。
嗯,就把这整块换成我们需要的就行了。
四.上传图片的思路:
- 图片插入框,最简单的就是
<input type="file" id="xxx">
- 将这个file文件通过ajax传到后端,上传之前可以先做一下文件类型的判定
- 后端处理文件需要先创建File对象,生成一个随机文件名(UUID),设置文件要保存的本地路径,保存文件之后把之前生成的随机文件名存到数据库,下次要读取文件就直接通过文件名读取。
- 生成的文件名和项目访问地址之类的加工一下就是可访问的URL了,ajax将URL返回给前端,前端就可以通过URL访问到图片了,这时候仿造上方的 cmdImge的回调函数,将URL按照 md语法格式插入编辑框内就行了。
我的实现方法:
我是直接把原本的cmdImge的回调函数整个舍弃了,按照前面的四步获取URL后,直接按照md语法格式插在光标后方。
五.改写js文件的方法:
前端方面我也不是很熟,我就直接把html里的jquery函数搬到js里了(因为我用了模态窗口组件,所以我需要在点击插入图片之后去自动触发模态窗口的按钮来实现我的功能。这里一般是可以直接调用function函数的,因人而异吧),能成功运行,不过这样的缺点就是每个调用Bootstrap-markdown编辑器的html页面都需要有一个对应的自定义函数。
如图:
效果图: