利用html5 file api读取本地文件(如图片、PDF等)

news/2024/7/24 13:17:04 标签: 数据结构与算法, javascript

在html4的年代,我们如果要在网页上呈现一张用户本地的图片,需要用户先把图片上传到服务器,再根据服务器提供的图片地址把图片下载下来,才能把图片在网页上呈现出来。这一来二往,起码已经费了两倍于这张图片的流量了,更别说服务器为了存储这张图片所花费的资源以及用户上传错了图片的冤枉成本(因为在html4时代,用户选择好图片后,往往只能看到图片的文件名,而无法通过预览图来进一步确认这张图片是否就是自己想要上传的)。 html5提供了新玩法,光靠浏览器,就可以对本地的(其实也可以是远程的)文件(主要是图片)进行呈现、读取、处理等操作,而这一切,则是通过html5 file api来实现的。

首先是数据结构,html5定义了一个file对象类型来表示文件,每个file对象对应一个文件。file对象有3个属性:name、size、type。name是不包含路径的文件名,size是以字节为单位的文件体积大小,type则是文件的MIME(例如image/jpg)。 file对象不单独存在,而是以数组形式,存在一个名为FileList的数组中。那么,如何拿到这个FileList数组呢?目前,html5有两个途径可以拿到FileList,一是通过file类型的input,二是通过拖放操作的drop事件。

通过file类型的input获取FileList

<input id="file-input" type="file" />
复制代码

或html5新增的可进行文件多选的multiple属性:

<input id="file-input" type="file" multiple />
复制代码

一般,我们都是给input:file绑上一个onchange事件,以便在用户选定文件后,马上进行读取文件等下一步操作:

//原生js
var inputElement = document.getElementById("file-input");
inputElement.addEventListener("change", handleFiles, false);
function handleFiles() {
  var fileList = this.files; 
}

//jquery版
$('#file-input').on('change', function() {
    var fileList = this.files;
});
复制代码

通过拖放操作drop事件

首先要设定一个可供拖放的区域:

<div id="dropbox" style="width: 200px;height: 200px;"></div>
复制代码

另外,为了能触发drop事件,我们必须阻止dragenter和dragover事件的默认行为:

var dropbox;
dropbox = document.getElementById("dropbox");
dropbox.addEventListener("dragenter", dragenter, false);
dropbox.addEventListener("dragover", dragover, false);
dropbox.addEventListener("drop", drop, false);
function dragenter(e) {
  e.stopPropagation();
  e.preventDefault();
}

function dragover(e) {
  e.stopPropagation();
  e.preventDefault();
}
复制代码

然后,我们就可以在drop事件的callback中,获取到fileList:

function drop(e) {
  e.stopPropagation();
  e.preventDefault();

  var dt = e.dataTransfer;
  var files = dt.files;

  handleFiles(files);
}
复制代码

怎么读取或利用file对象呢?

html5提供了两个方案:FileReader和ObjectUrl。

使用FileReader读取file对象

首先需要实例化FileReader对象:

var reader = new FileReader();
复制代码

利用FileReader读取file对象是一个异步的过程,我们需要先为FileReader设置好load事件的callback,告知FileReader在读取到file对象的数据后应该进行什么进一步的操作:

reader.onload = function(e) { 
    document.getElementById("image").src = e.target.result; 
}
复制代码

上面这段代码的意思是,FileReader读取到图片的数据后,把数据(DataUrl)放到的src属性里。 最后,就是通过FileReader不同的方法,来决定读取file对象数据后用什么数据格式来存放,并实施读取:

  1. readAsArrayBuffer(file) :读取file对象并存放为ArrayBuffer对象(ArrayBuffer对象是什么我暂时没有搞清,应该是一种为了高效存取数据而产生的数据结构)。
  2. readAsText(file [, 'UTF-8']) :以一般文本模式读取file对象,值得注意的是,利用第二个参数(可选)可指定字符编码。
  3. readAsDataURL(file) :读取file对象并存放为data: URL格式的字符串。

利用ObjectURL

ObjectURL相当于文件的一个临时路径,此临时路径可随时生成、随时释放,在本地浏览器使用起来时,与普通的url无异。 以把一张本地图片显示在页面上为例:

var img = document.createElement("img");
img.src = window.URL.createObjectURL(file);
复制代码

此时,src形如:blob:http://test.local.com/e03e8bbf-66ce-4fea-a8c8-772f9fdb4d40 用这个src就能让浏览器从本地读取图片。 这种方案相对用FileReader生成图片的base64编码并放到的src里来说,性能有了很大的提升。

比较这两种读取File对象的方案,FileReader适合用来上传文件,而ObjectURL则适合直接在浏览器进行操作,然后操作后再把处理后的数据进行上传,例如利用canvas截图或进行图片压缩等。当然,这一切都是要考虑兼容性的。


http://www.niftyadmin.cn/n/1558166.html

相关文章

node.js 学习---第二章

上一章 下一章 npm 包管理器简介 npm 是 Node.js 标准的软件包管理器。 它起初是作为下载和管理 Node.js 包依赖的方式&#xff0c;但其现在也已成为前端 JavaScript 中使用的工具。 yarn Yarn是facebook发布的一款取代npm的包管理工具 1&#xff09;速度超快----Yarn缓存…

「镁客·请讲」博雅工道熊明磊:专注消费者体验,做没有“尾巴”的水下机器人...

在熊明磊看来&#xff0c;使用门槛和价格的降低是立足消费级市场的成功所在。 从去年开始&#xff0c;在天空已经被大疆等厂商占据的情况下&#xff0c;水下成为了一个新的“战场”。更为准确的说&#xff0c;“水下机器人”市场一直都存在&#xff0c;只是去年逐步走进了大众…

node.js 学习---第三章

上一章咱们提到package.json&#xff0c;现在便详细学习一下。 如果使用 JavaScript、或者曾经与 JavaScript 项目、Node.js 或前端项目进行过交互&#xff0c;则肯定会遇到过 package.json 文件。 package.json 指南 name注释version表明了当前的版本。name设置了应用程序/…

【转】oracle 和 ' 特殊字符处理 ( like 'GAC/_%' escape ''; 这里面的 / 居然将 转义了 为什么?)...

原文地址&#xff1a;http://blog.csdn.net/gjswxhb/article/details/6083242 今天在导入一批数据到Oracle时&#xff0c;碰到了一个问题&#xff1a;Toad提示&#xff08;plsql 也一样&#xff09;要给一个自定义变量AMP赋值&#xff0c;一开始我很纳闷&#xff0c;数据是一系…

部署vue项目到阿里云服务器(Ubuntu16.04 64位)

上传文件 1.通过Xftp将vue项目文件上传至云服务器&#xff1b;由于node_modules这个依赖包体积较大&#xff0c;上传较慢&#xff0c;上传时跳过&#xff0c;在云服务器上重新进行npm install安装依赖包即可&#xff1b; 2.也可通过git clone从github上克隆项目&#xff08;首先…

node.js 学习---第四章

这里写目录标题node 事件循环process.nextTicksetImmediatePromise 简介链式 promise为什么引入 async/awaiteventsnode 事件循环 事件循环这里就不详细描述了&#xff0c;如果不太了解可以看看前端–事件循环机制 下面是node官网提供的一个示例。 const bar () > conso…

安卓动态调试七种武器之长生剑 - Smali Instrumentation

蒸米 2015/05/15 10:010x00 序随着移动安全越来越火&#xff0c;各种调试工具也都层出不穷&#xff0c;但因为环境和需求的不同&#xff0c;并没有工具是万能的。另外工具是死的&#xff0c;人是活的&#xff0c;如果能搞懂工具的原理再结合上自身的经验&#xff0c;你也可以创…

node.js 学习---第五章

node学习搭建 HTTP 服务器fs文件描述符文件属性path文件路径从路径中获取信息使用路径 join、resolve、normalize读取文件 readFile写入文件 writeFile搭建 HTTP 服务器 const http require(http)const port 3000; const addr require(address) const ip addr.ip();cons…