Axios 上传文件到七牛云的坑坑洼洼
需求
上传文件也就当初还在用php写前端得时候, 直接使用form, 然后button submit提交到后台上去. 后面使用微信小程序提交文件得时候也就跟简单咯, 直接调用官方sdk就可以了, 这次由于项目上需要使用vue这种面向mvvm的框架直接上传文件, vue的核心就是不操作DOM, 所以我们最好也要尊重vue的设计核心思想嘛.
本来element这些框架是有封装好的上传组件, 使用起来也非常的方便api友好. 不过考虑到我本次项目追求的是轻量简洁, elementUi暂时不做考虑.
百度查询了一下资料, vue中上传文件一半都是在 input 上绑定@change=”handleFileChange” 事件, 然后在handleFileChange函数中New一个formData对象将我们需要上传的内容append添加好, 通过axios直接post发送到服务器上. OK 流程知道了那就开动吧
实操
先写一个inpu type为file类型的文件选择输入框
1 | <input type="file" @change="handleFileChange" ref="upload"> |
接下来直接也对应的函数
1 | handleFileChange(){ |
理论上做到这个地步应该就可以了嘛, 但是我们跑一下 ..会直接报 400
1 | {error: "invalid multipart format: request Content-Type isn't multipart/form-data"} |
Content-Type不是Form-data ??? 作为一个半吊子程序猿, 这些错误是完全不认识的. 中鞥依靠万能的百度, 搜了一下啊,说是要在请求的header中定义Conten-type属性.
查看一下本次请求的header信息.
1 | Content-Type:application/x-www-form-urlencoded |
试着在$ajax添加一句
1 | headers:{'Content-Type':'multipart/form-data'} |
ctrl + s 刷新重试, 还是400 …emmm
1 | {error: "invalid multipart format: no multipart boundary param in Content-Type"} |
没有boundary param ???, 百度了一下, 原来七牛云需要boundary这个参数
试着将头部信息改成这样
1 | headers:{'Content-Type':'multipart/form-data; boundary='+ new Date().getTime()} |
1 | {error: "invalid multipart format: multipart: NextPart: EOF"} |
—– emmmm 实在搞不懂了, 我们不用axios上传的时候完全没有问题嘛, 接着百度搜了一下, 原来axios在请求的时候会拦截我们的headers. 我们可以直接creat 一个干净的axios对象进行提交
1 | // 重新导入axios, 不能直接使用挂载到vue上的 |
Ctrl + S 随便丢张图 这些终于200咯
最后代码
1 | <!-- accept 在网上看到x5内核浏览器上会出现选择图片无效的情况, 需要设置accept属性 "image/jpeg, image/png, image/gif" --> |
总结一下
都是axios的锅, 不是我太菜. 对 全是axios的错
input中如果两次同时选择同一个文件不会触发@change事件. 所以我们每一次上传完成后就可以清空一下input
1 | this.$refs.upload.value = null |