近期的需求中包含了上传头图(图片)和上传菜品(excel文件)的功能,商家可灵活上传使用自己制作的问卷图片,用户评价上传的菜品。
今天就针对我在做图片上传和excel上传时遇到的一些问题,跟大家分享一下
<input>
type=file 的 input 元素,该元素可以允许用户选择一个或者多个文件。
该元素包含一个文本输入字段,用来输入文件名,还有一个按钮,用来打开文件选择对话框,以便图形化选择文件。
1. accept='image/png' 或者 accept='.png' 表示只接受 .png 格式的图片 2. accept='iamge/png,image/jpeg' 格式的图片 3. accept='image/*' 接受所有类型的 image
注:image/*
在部分浏览器(Chrome和Safari等Webkit浏览器)响应比较慢,可以按照第二种方式展示 imgage/png,image/ipeg
<input type="file" />
显示替代的文字就这样,一个简单的文件选择的功能咱们就做好了,可以设置属性来限制文件上传的格式、大小等来优化咱们的功能。 当然,这时你会发现:
HTML
自带的上传按钮比较丑,如何对其进行美化呢?咱们一步步来完善
先把之前的按钮透明度opacity
设置为0,然后外层用div
包裹,就实现了美化功能
代码如下:
DOM结构:
<div className="file_upload">
选择文件
<input
id="myFile"
type="file"
name="inputFile"
onChange={this._onChangeInputFile.bind(this)} />
</div>
CSS样式:
.file_upload {
position: relative;
width: 100px;
height: 40px;
line-height: 40px;
text-align: center;
border-radius: 6px;
background-color: #79d479;
color: #fff;
}
.file_upload input {
position: absolute;
width: 100%;
height: 100%;
opacity: 0;
top: 0;
left: 0;}
修改前后如下:(也可以看一下manage_v2017项目中“图片预览”组件的样式美化)
如果我们先将图片上传到服务器,然后在将返回结果显示在前端,这样的操作性能开销太大,如果图片很多,就比较慢了。
选中文件通过 HTMLInputElement.files 属性返回了一个 FileList 对象,这个对象是一个包含了许多 file 文件的列表。每个 file 对象包含了一下信息:
我们可以通过对input的change事件监听,获取FileList.
const files = document.getElementById('uploadFile').files;
let fileObj = files[0];
当我们获取到文件信息files后,需要将选择的图片展示在页面上,要用到FileReader;他是用来把文件读入内存,并且读取文件中的数据。它提供了一个异步的API,使用该API可以在浏览器主线程中异步访问文件系统,读取文件中的数据。他必须先通过 FileReader() 构造函数创建出一个 fileReader 实例,实现图片预览要用到它的几个方法和属性。想要了解FileReader更多
<img src="" id="PreviewImg" />
<input type="file" id="uploadImg" onChange={this._onChangeImg.bind(this)} />_onChangeImg(e) {
let fileObj = document.getElementById("uploadImg").files[0],
PreviewImg = document.getElementById("PreviewImg"),
reader = new FileReader(); // 读取文件并以数据 URI 形式保存在 result 属性中
reader.readAsDataURL(fileObj); // 在文件加载成功后触发 load 事件
reader.onload = function(e) {
let imgUrl = e.target.result;
PreviewImg.src = imgUrl;
} // 在文件加载失败后触发 error 事件
reader.onerror = function(e) {}}
FileReader 的实例拥有 4 个方法,其中 3 个用以读取文件,另一个用来中断读取。下面列出了这些方法以及他们的参数和功能,需要注意的是 ,无论读取成功或失败,方法并不会返回读取结果,这一结果存储在 result属性中。
FileReader 包含了一套完整的事件模型,用于捕获读取文件时的状态,下面归纳了这些事件。
使用对象 URL 的时候不用像 FIleReader 一样要先把数据读取到 JavaScript 中,他可以引用 内存中 URL 地址而使用。
创建对象 URL 方法: window.URL.createObjectURL()。兼容写法:
<img src="" id="PreviewImg" />
<input type="file" id="uploadImg" onChange={this._onChangeImg.bind(this)} />
function creatObjectURL(file) {
if (window.URL) {
return window.URL.createObjectURL(file);
} else if (window.webkitURL) {
return window.webkitURL.createObjectURL(file);
} else {
return null
}
}_onChangeImg(e) {
let fileObj = document.getElementById("uploadImg").files[0],
PreviewImg = document.getElementById("PreviewImg"); let url = this.createObjectURL(fileObj);
PreviewImg.src = url;}
区别: 参(zhao)考(chao)
FileReader 是异步操作,而对象 URL 是同步操作FileReader.readAsDataURL 返回的是一个包含更多字节的 base64 格式,createObejctURL 返回的是一个带 hash 的 URL。由于两者返回形式不同,FileReader.readerAsDataURL 会占用更多内存,但是当你不再使用他的时候,他会自动释放内存,而 createObjectURL 则只有当你的页面关闭或者手动调用 revokeObejctURL 的时候才能释放内存。从兼容性来说: createObjectURL 和 FileReader.readerAsDataURL 都兼容 IE10+ 和现代所有主流浏览器createObjectURL 相对 FileReader.readerAsDataURL,效率较高。但是如果图片较多,则最好手动清除内存,可以把 URL 当做参数直接传给 window.URL.revokeObjectURL()。兼容写法:
function revokeObjectURL(url) {
if (widnow.URL) {
return window.URL.revokeObjectURL(url)
} else {
return window.webkitURL.revokeObjectURL(url)
}
}
参考资料: