背景
先看一下目前的效果:在「Markdown 笔记」原有的上传图片弹窗中增加了一个我们自定义的上传按钮,通过直接与后端 API 交互完成图片上传(相关 API 是「笔记」上传时公开使用的)。
两年前还没开始使用 GitHub 记录读书笔记,那时在用有道云笔记。我使用的是 「Markdown 笔记」,在最开始一段时间没有上传图片的需求,所以用起来还可以。后来开始记录《Head First 设计模式》的读书笔记,并画了每个模式的类图,开始有了上传图片的需求,而官方将 「Markdown 笔记」上传图片的功能仅对会员开放。
穷则思变,机智的我就注意到了以前使用「笔记」时可以直接上传图片,并且没有会员限制,将这个图片的链接放到「Markdown 笔记」内也可正常使用。所以就先人工操作,每次需要上传图片时,先切到一个自己建立的用于上传图片的「笔记」,图片上传成功后再将链接拷贝回「Markdown 笔记」,暂时解决了上传图片的需求。
懒是第一生产力,做程序员最大的好处就是可以通过写代码简化日常网上活动的各种重复性操作。在按照前面的方式完成几篇带图片的「Markdown 笔记」后,就开始感到厌烦,这一操作机械重复没有任何价值,所以就想到很适合通过代码自动执行。
实现流程
由于我们需要的图片上传功能在「Markdown 笔记」页面中没有,所以不能使用操作页面元素的方式,只能通过抓 API ,并且自己调用 API 来实现图片上传。
封装 API
封装 API 前我们需要抓 API ,这个很简单,其实就是触发一下我们所需要实现的功能,然后查看浏览器发送了哪些请求,记住这些请求并封装一下,以便后续调用。
「笔记」图片上传操作后会发现浏览器发送了三个请求:
- 第一个是获取
transmitId
以供后续两个请求使用 - 第二个是使用
transmitId
上传图片(这里仅实现了小文件单次上传) - 第三个是使用
transmitId
给上传完成的文件添加各种信息,并获取图片地址
一个简单的图片上传只需要三个请求,所以我们先封装一下,具体实现可以在 api.js 找到(其中还封装了其他 API ,不过后续没有使用到)
封装上传组件
点击完上传后,我们需要一个组件来实现选择图片、上传图片、返回图片地址这三个操作。我们在前面封装的 API 已经实现了上传图片并返回图片地址的功能,所以在这里我们这个组件只需要能触发选择图片逻辑即可。我们可以通过 <input type="file">
来实现选择文件的功能,然后我们需要对其注册 change
事件,用于当用户选择完图片后,实现后续的操作逻辑。
// 上传文件,触发后,会选择文件,并执行上传文件获取url,最后执行回调(回调的第一个参数是文件,第二个参数是上传的url)
function upload(accept, callback) {
// 1. 创建 input 节点
if($('#diy-uploader-input').length == 0) {
$('body').append('<input id="diy-uploader-input" type="file" style="position: absolute; top: -1000px; left: -1000px;" accept="'