Vue组件放送之文件上传
栏目: JavaScript · 发布时间: 6年前
内容简介:文件上传组件是常见的 Web 组件。HTML 提供了 input file 原始上传组件,我们在此基础上利用各种 HTML5 特性来封装该组件,而不是通过内嵌一个隐藏 Flash 上传(古老的做法)。又因,利用了 vue 的 MVVM 和组件化的强大特性,这一切都变得简单轻松。先谈谈组件的需求——一般图片上传的场景较多,故该组件除了任意文件上传,还特意针对图片上传来开发:下面我们逐一分析需求的解决办法。
文件上传组件是常见的 Web 组件。HTML 提供了 input file 原始上传组件,我们在此基础上利用各种 HTML5 特性来封装该组件,而不是通过内嵌一个隐藏 Flash 上传(古老的做法)。又因,利用了 vue 的 MVVM 和组件化的强大特性,这一切都变得简单轻松。
先谈谈组件的需求——一般图片上传的场景较多,故该组件除了任意文件上传,还特意针对图片上传来开发:
- 可以无刷新上传可以无刷新上传
- 可以美化 input file 元素,允许自定义样式可以美化 input file 元素,允许自定义样式
- 可以预览本地图片
- 可以先压缩图片大小或者自定义分辨率
- 可以检测文件扩展名、文件大小、实际文件类型检测、图片分辨率大小
- 可以在弹出的文件选择框限制文件类型
- 可以显示上传进度
- 可以断点续传
- 在 iOS 上,有照片旋转不正确的问题,这个问题也必须得到解决。在 iOS 上,有照片旋转的问题,这个问题也必须得到解决。
下面我们逐一分析需求的解决办法。
XHR 2.0 文件上传
无刷新上传,实际上在 XHR 2 之前我一直使用 iframe 实现,原理是隐藏一个 ifame 并赋予 id,然后 form 表单 target 属性指向的就是那个 iframe id,这会形成是 ifame 上传的文件,表单的目的地是该 iframe,又因 iframe 是隐藏的,故能实现“无刷新”上传。
不过坑也不能避免的,一个表单是不允许嵌套另外一个表单的,所以我写这种 vue 组件时十分累,避免在同一个 iframe 中,要写大量 dom 控制语句,而且又要考虑多个上传组件的话,更麻烦了。
后来XHR 2.0 即 XmlHttpRequest 2.0 支持文件上传,问题迎刃而解。
var fd = new FormData();
if(this.$blob){ // File 类型不需要文件名,Blob 强制需要
fd.append("file", this.$blob, this.$fileName);
} else
fd.append("file", this.$fileObj);
var xhr = new XMLHttpRequest(), self = this;
xhr.onreadystatechange = ajaxjs.xhr.callback.delegate(null, this.uploadOk_callback, 'json');
xhr.open("POST", this.action, true);
xhr.onprogress = function(evt) {
var progress = 0;
var p = ~~(evt.loaded * 1000 / evt.total);
p = p / 10;
if(progress !== p) {
progress = p;
console.log('progress: ', p);
}
self.progress = progress;
};
xhr.send(fd);
原理比较简单,就是 FormData 作为容器放置 file/blob 对象。注意 blob 必须指定文件名,否则后台会报错。
如上所见,XHR 包含了进度反馈的功能,也就是 progress 事件。于是把第9点需求也解决了。
美化上传按钮
如何美化就是样式 CSS 问题了。我们知道 label 标签有个特性,在设置了 for 属性后(该值是一个 id),就是点击标签文本会使得 id 所在的元素获得焦点,典型如 input 元素。有一个便捷不用设置 id 的方法就是 label 包含提示文字和 input 两者。
利用该方法,我们于是可以隐藏一个 input,然后通过 for/id 关联起来 label 与 input 元素,如下代码所示。
<label for="uploadInput_663"> <div><div>+</div>点击选择图片</div> </label> <input type="file" id="uploadInput_663" accept="image/*" class="hide">
实际丑陋的 input 界面被隐藏了,我们可以随心所欲地美化 label 标签,如我制作的,
但背后依然调用 input 的功能。
值得一提的的是, H5 可自定义弹出的文件选择框限制文件类型,如属性 accept=“image/” 表示只选择 图片 来上传,非常简单。
预览本地图片
我们知道 < img src=“xxx” /> 元素的图片可以是一个 url,或者 base64 编码的文本。图片还未上传到服务器,自然就没用所谓的 url,自然应该从 base64 方面“打主意”。H5 为我们提供 file 类型对象及其读取器 file reader,可以在浏览器本地读取到客户端计算机里面的图片,并转换为 base64 编码。先说说 File 对象,
// 当前 input file 元素触发的 onchange(e) 事件如下
this.$fileObj = e.target.files[0]; // 保留 File 对象 的引用。数组表示可以多选文件
this.$fileName = this.$fileObj.name; // 文件名
this.$fileType = this.$fileObj.type; // 文件类型,MIME
var size = this.$fileObj.size; // 文件大小
// 文件头判别,看看是否为图片
var imgHeader = {
"jpeg" : "/9j/4",
"gif" : "R0lGOD",
"png" : "iVBORw"
};
for ( var i in imgHeader) {
if (~imgBase64Str.indexOf(imgHeader[i])) {
self.isExtName = true;
return;
}
}
self.errMsg = "亲,改了扩展名我还能认得你不是图片哦";
// 转换为 base64 字符串
var reader = new FileReader();
reader.onload = function(e) {
var imgBase64Str = e.target.result; // 得到了图片的 base64 编码
……
}
reader.readAsDataURL(file);
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- Vue组件放送之下拉省市区联动
- 用NodeJS实现反爬虫,原理&源码放送
- MILA 2018夏季深度学习与强化学习课程资源大放送
- 给AI开发者的新年礼物,技术公开课大放送(附演讲PPT)
- 当云计算、开源大神们聚在一起,他们会讲什么?两大盛会议程放送!
- React 组件模式-有状态组件 x 无状态组件、容器组件 x 展示组件、高阶组件 x 渲染回调(函数作为子组件)
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
ACM/ICPC程序设计与分析
沈云付 / 清华大学 / 2010-7 / 39.50元
《ACM/ICPC程序设计与分析(C++实现)》介绍ACM国际大学生程序设计竞赛概况及程序设计基础,系统介绍数论、组合数学、动态规划、计算几何、搜索、图论和网络流等专题的典型算法,挑选历年竞赛中许多有代表性的竞赛题作为例题进行分析,便于学生编程时模仿学习。每章的例题和习题都配有输入输出样例,方便学生在编程时测试与调试程序。《ACM/ICPC程序设计与分析(C++实现)》以C++为程序设计语言,以提......一起来看看 《ACM/ICPC程序设计与分析》 这本书的介绍吧!