xtzero.me
Editor.md + 七牛云 实现在文本框粘贴图片上传到七牛云,并实时更新上传进度到文本框
技术学习
2023-10-24 17:33:59

先准备一个 div 给 Editor.md 渲染用:

<div id="editormd-container"></div>

渲染逻辑

this.Editor = editormd("editormd-container", { width: "100%", height: 640, syncScrolling: "single", path: "/public/js/editor-md-lib/", });

由于七牛云部分是使用了客户端上传,参考了官方的js sdk 文档。所以需要提前用后端把七牛云的上传 token 准备好。这里就默认我已经将 token 放到this.qiniuToken中了。

在编辑器加载完毕后,绑定粘贴事件。

this.Editor = editormd("editormd-container", { width: "100%", height: 640, syncScrolling: "single", path: "/public/js/editor-md-lib/", onload: function() { document.addEventListener("paste", function (e) { var items = (e.clipboardData || e.originalEvent.clipboardData).items for (var i = 0; i < items.length; i++) { if (items[i].type.indexOf("image") !== -1){ var blob = items[i].getAsFile(); var reader = new FileReader(); reader.onload = function (event) { const imageData = event.target.result // imageData 就是图片的 base64数据 }; reader.readAsDataURL(blob); } } }); } });

接下来需要准备两个工具函数

// base64 转 Blob function base64ToBlob(base64, type) { const binaryString = atob(base64); const length = binaryString.length; const bytes = new Uint8Array(length); for (let i = 0; i < length; i++) { bytes[i] = binaryString.charCodeAt(i); } return new Blob([bytes], { type: type }); } // Blob 转 File 对象 function blobToFile(blob, fileName) { return new File([blob], fileName, { type: blob.type }); }

在获取到图片的 base64 数据后,将其转换为 File 对象,就可以直接调用七牛云的 sdk 进行上传了。

我们先将 base64 转为 File 对象:

const blob = base64ToBlob(imageData.replaceAll('data:image/png;base64,', ''), "image/png") // rand 是个生成随机数的函数,随便一搜就能搜到 const fileName = `${md5(`${Date.parse(new Date())}`)}${rand(100000, 999999)}` const file = blobToFile(blob, fileName)

紧接着,我们向文本框中粘贴的位置插入一个占位字符串,用来更新图片上传进度和上传完成后直接显示图片。

// 编辑器实例存放在 _this.Editor 中 // 由于是在 onload 事件中,而 onload 事件是用 function 的形式写的 // 所以需要在 onload 外面提前用 `const _this = this` 把当前 Vue 实例存起来 // fileName 是上面一段代码中生成的随机文件名 _this.Editor.insertValue(`![图片上传中 0%](${fileName})`)

后面要实现的逻辑是,当图片上传进度变化时,我们要将进度更新到这个占位串中;当图片上传完毕,我们要将图片的服务器地址更新到这个占位串上。

// 开启一个七牛云的上传任务
const observable = qiniu.upload(file, `childPath/${fileName}`, _this.qiniuToken)

// 订阅七牛云的上传事件
const subscription = observable.subscribe((e) => {
	// 上传中途,更新图片的上传进度
	_this.Editor.setMarkdown(
		addVm.$refs.md.Editor.getMarkdown().replace(
			new RegExp(`\\!\\[图片上传中 (\\d+(\\.\\d+)?%)\\]\\(${fileName}\\)`, 'g'),
			`![图片上传中 ${e.total.percent.toFixed(2)}%](${fileName})`
		)
	)
}, (e) => {
	// 上传失败,删除编辑框里的图片
	_this.Editor.setMarkdown(
		addVm.$refs.md.Editor.getMarkdown().replace(new RegExp(`\\!\\[图片上传中 \\d+%\\]\\(${fileName}\\)`, 'g'), ``))
}, (e) => {
	// 上传完毕,更新图片显示
	_this.Editor.setMarkdown(
		_this.$refs.md.Editor.getMarkdown().replace(
			new RegExp(`\\!\\[图片上传中 (\\d+(\\.\\d+)?%)\\]\\(${fileName}\\)`, 'g'),
			`![${fileName}](http://host.com/${e.key})`
		)
	)
})
xtzero.me
从前从前,有个人爱你很久
友情链接
这里是友情链接
虽然我很菜,但是也希望可以和更多人交换友链。
作品站
这里是我的 作品站
虽然菜,但还没放弃创造。
推广内容
或许你需要买便宜的服务器
你有优惠我有返利,何乐而不为呢。

立即查看 >>
也想使用 Hikari 2 ?
Hikari 2 已经被用来建站啦!点击这里来查看都有哪些案例以及我们的联系方式吧。