js 中 文件流的截取處理

問題背景:

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章