问题背景:
项目开发的中有一个这样的场景,在前端页面中实现一个markdown的文本编辑器,对md文件进行编辑、预览和保存。在看了github上的issue模块以及一些论坛的回复功能模块。基本的实现流程是这样的。现在以markdown为例:
1、后端将存在数据库中的md文件解析成json格式的字符串(.md源码)传给前端
2、前端接收到 .md 源码的字符串 进行编辑,完成之后 点击保存将 编辑后的 .md 源码的字符串 传给后端服务器
3、后端将 .md 源码的字符串生成 .md 的文件存在数据库
可以看到整个过程中前端的处理很简单,仅仅是对字符串进行处理,难点无非是自己实现一个markdown编辑器插件或者从网上找一个插件。而所有的文件解析处理工作全部放后端来处理。
这个需求实际是一个优化需求,之前是不支持展示和编辑功能,仅仅是一个.md文件的上传和下载。在后端功能不变(即仅提供文件的存取功能)的情况下实现这个需求,这些解析工作就需要放前端来处理了。
解决思路:
1、将下载.md文件的过程,转为截取文件流 转为md源码字符串作为一个变量存在内存中
2、对字符串进行处理后 转为.md文件上传后端。
前端获取文件一般都是用动态生成a标签,或者iframe标签来进行下载 如
// iframe的方式
function createDownloadIframe (src, showModal) {
const target = document.getElementById('downIframe')
if (target) {
document.body.removeChild(target)
}
const htm = document.createElement('iframe')
htm.setAttribute('src', src)
htm.setAttribute('id', 'downIframe')
htm.style.display = 'none'
document.body.appendChild(htm)
if (htm.attachEvent) {
htm.attachEvent('onload', () => {
...
})
} else {
htm.onload = () => {
...
}
}
}
// a标签的方式
const a = document.createElement('a'); // 创建a标签
a.setAttribute('download', ''); // download属性
a.setAttribute('href', ''); // href链接
a.click();// 自执行点击事件
现在这一步需要做的操作就是下载过程转为获取流过程
// 用原生js的XMLHttpRequest 发送请求的方式:
function catchBinary (url) {
let xmlHttpRequest = new XMLHttpRequest()
xmlHttpRequest.open('GET', url, true)
xmlHttpRequest.setRequestHeader('Content-type', 'application/json')
xmlHttpRequest.responseType = 'blob'
xmlHttpRequest.onload = function (oEvent) {
let content = xmlHttpRequest.response
let reader = new FileReader()
reader.readAsText(content)
reader.onload = function (evt) {
if (evt.target.readyState === FileReader.DONE) {
cb && cb(reader.result)
}
}
}
xmlHttpRequest.send()
}
// 因为本项目为vue + axios 项目所以 用axios封装好的方法
getMDFileBinary (url) {
return axios({
method: 'get',
url: url,
responseType: 'blob'
})
}
getMDFileBinary(url).then(response => {
let reader = new FileReader()
reader.readAsText(response.data)
reader.onload = function (evt) {
if (evt.target.readyState === FileReader.DONE) {
__this.value = reader.result
}
}
})
这样第一步获取工作就完成了,接下来进行第二步
第二步 将字符串生成文件并上传
// 处理文件
const md = this.md // md 源码 (本项目为 vue项目 this.md)
const mdFile = new File([md], 'text.md')
let formData = new FormData()
formData.append('file', mdFile )
setMDFileBinary(url, formData).then(res => {
console.log(res.data)
})
function setMDFileBinary (url, data) {
return axios({
method: 'post',
url: url,
data: data,
headers: {
'Content-Type': 'multipart/form-data'
}
})
}
DONE。。。
这样基本的功能就完成了
TODO
1、兼容性问题: mavon-editor 不支持ie浏览器
2、。。。
知识点和工具:
一款markdown编辑器 mavon-editor
axios
Blob
FileReader
XmlHttpRequest
FormData
File