問題背景:
項目開發的中有一個這樣的場景,在前端頁面中實現一個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