本文首发于公众号:符合预期的CoyPan
在前端开发中,咱们常常会遇到对文件的操做,特别是对图片的操做。在Node端,提供了file相关的接口,供咱们使用。在浏览器中,Html5提供了File相关的Web Api。javascript
本文将小小总结一下如何使用File相关的api来操做文件以及相关的一些知识。html
一个File对象包含了如下的属性:前端
lastModified: 只读。文件最后修改时间(UNIX时间戳)。 name: 只读。文件名(不包含完整路径)。 size: 只读。文件大小。 type: 只读。MIME TYPE。
看一个例子:java
在浏览器中,咱们也能够直接使用File构造函数来构造一个文件对象实例。json
var json = `{ "a": 1 }`; var f = new File([json], 'test.json', { type: 'application/json' }); console.log(f);
一个File对象的内容能够是不少数据类型,包括:ArrayBuffer、ArrayBufferView、Blob、DOMString(在JS中,DOMString就是String)。本文不作进一步详细介绍。
那么,如何获取一个文件对象呢?上面提到了,咱们能够直接使用File构造函数。大多数的状况下,咱们是须要让用户进行选择,这个时候,就须要用到 input 标签了。代码也很简单,咱们只须要把input标签的 type 设置为 file 就行。api
<html> <input type='file'/> <script> const el = document.querySelector('input'); el.addEventListener('change', e=> { const fileList = e.target.files; [].slice.call(fileList).forEach(file => { console.log(file); }); }); </script> </html>
咱们只须要监听input标签的change事件,就能够拿到文件对象了。这里须要注意的时候,咱们拿到的实际上是一个文件列表,而这个文件列表是一个类数组对象,须要转换为数组,才能彻底像数组同样遍历。数组
若是想选择多个文件,则须要在input标签上增长 multiple 属性。若是只接受某些类型的文件,能够添加 accept 属性。浏览器
<!-- 能够多选文件 --> <input type='file' multiple /> <!-- 多选,只能选择图片文件 --> <input type='file' multiple accept='image/*'/>
上面的图中咱们能够看到,直接使用input标签是不太美观的。咱们能够将input标签隐藏,使用代码触发input标签的点击事件,就能够达到效果。app
<html> <input type='file' style="display:none"/> <button>这是一个帅气的按钮</button> <script> const inputEl = document.querySelector('input'); inputEl.addEventListener('change', e => { const fileList = e.target.files; [].slice.call(fileList).forEach(file => { console.log(file); }); }); const btnEl = document.querySelector('button'); btnEl.addEventListener('click', () => { inputEl.click(); }); </script> </html>
上面讲了如何拿到一个文件对象,那么怎么读取文件的内容呢?这个时候,就须要用到另一个Web Api了:FileReaderide
使用FileReader读取文件内容,主要步骤为:
// 一、声明一个FileReader对象实例 var fileReader = new FileReader(); // 二、监听读取完成事件 fileReader.onload = function(e) { const result = e.target.result; } // 三、读取文件内容 // 这里的 file 为文件对象。 fileReader.readAsDataURL(file); // 以base64的方式读取 // fileReader.readAsArrayBuffer() 以ArrayBuffer的方式读取 // fileReader.readAsText() 以字符串的方式读取
一个很常见的场景:读取本地图片,并展现缩略图。实现起来十分简单。
<html> <input type='file' accept='image/*' /> <script> const el = document.querySelector('input'); el.addEventListener('change', e=> { const imgFile = e.target.files[0]; const reader = new FileReader(); reader.onload = function(e) { const base64 = e.target.result; const imgEl = new Image(); imgEl.src = base64; imgEl.onload = function() { document.body.appendChild(imgEl); } } reader.readAsDataURL(imgFile); }); </script> </html>
想要在浏览器中预览文件,还有另一种方法:使用 window.URL.createObjectURL
window.URL.createObjectURL 能够接受一个文件对象做为参数,返回一个字符串。这个字符串是一个包含了一个对象URL,可用于指定源文件对象的内容。看下面的例子:
<html> <input type='file' accept='image/*' /> <script> const el = document.querySelector('input'); el.addEventListener('change', e=> { const imgFile = e.target.files[0]; const imgSrc = window.URL.createObjectURL(imgFile); console.log(imgSrc); const imgEl = new Image(); imgEl.src = imgSrc; imgEl.onload = function() { document.body.appendChild(imgEl); window.URL.revokeObjectURL(imgFile); } }); </script> </html>
能够看到,这里图片的src,是一个以 blob:
开头 的字符串。这是浏览器本身实现的一个协议,表示对一个资源的引用,须要挂载到网页中的资源对象上(好比img,video),才能展现出来。
下面的场景是比较常见的:在页面上生成一个自定义文件,而后下载下来。要实现这个需求,能够按照下面的思路:
代码示例:
<html> <button>点击下载</button> <script> const btnEl = document.querySelector('button'); btnEl.addEventListener('click', function() { const json = `{ "a": 1 }`; const file = new File([json], 'test.json', { type: 'application/json' }); const url = window.URL.createObjectURL(file); const aTag = document.createElement('a'); aTag.href = url; aTag.download = 'test.json'; aTag.click(); }); </script> </html>
本文主要介绍了在前端页面中,如何处理File。其实File对象是继承自Blob对象,File是特殊的Blob。Blob 是 Binary Large Object 的缩写,表示一个不可变、原始数据的类文件对象,主要用于处理二进制的数据。关于这一部分的内容,能够移步这篇文章.
另外,最新版的Chrome已经支持直接读写本地文件了。点我