加载文件 API

分享于 

22分钟阅读

Web开发

  繁體

在10天内开发 Windows 8应用程序。

为什么头像上传限制了我们的档案大小? 因为你知道,"请选择图像( 最大 50 KB ) ),为什么照片操作网络应用还没有实现,因为的画布已经出现了一段时间了? 这两个问题的答案归结于性能。 到目前为止,我们需要一个缓慢的插入或者通过服务器的路由来创建和修改浏览器中的文件。 但对于 IE 10.Firefox 和 Chrome 用户来说,开发人员在它的阿森纳中拥有出色的文件 API,使这些操作在浏览器中。

File是一个新的JavaScript,它允许你读取和写入表示Web应用程序中的文件的二进制数据对象。 简单地说,你可以将用户选择的文件读入Web应用程序,并将新的数据对象下载。 让我们来深入看看。

分解文件 API

File (。由W3C定义的 ) 不是一种类型,而是类型化对象。函数和方法的Collection。

文件组

FileList 是一个存在于许多地方的类型化对象。 首先,作为类型为"文件"的表单输入元素的属性。 其次,作为放置在放置文件事件或者 Clipboard 事件( 复制和粘贴的结果) 上的事件的一部分。

例如假设你有一个表单输入控件,如:

<input type=file onchange="console.log(this.files.length)" multiple/>

当用户单击表单输入并选择一个文件时,这里操作将调度 onchange 事件处理程序,FileList 对象( 位于 this.files relative 到输入元素)。 在本示例中,用户选择的文件数将打印到浏览器控制台。

在数组中,FileList 对象与本机数组类似,因为你可以对它的内容进行迭代。FileList 只包含文件对象的不可变实例( 下一步描述)。

文件

File 对象表示 FileList的单个文件。 File 对象包含只读元数据的哈希值,包括 NAME。最后修改日期。大小和类型。 它也被用作引用,并可以传递到 FileReader 以读取它的内容。

Blob ( 二进制大对象)

Blob接口公开文件的原始二进制数据。 远程数据可以作为blob对象通过 XHRRequest -if xhr.responseType 设置为"blob"。 新的Blob对象是一个into实例,包括 blob.slice(i,i+n),,它可以用于将大的Blob对象切片到小的Blob对象。 ( 在谈论JavaScript对象类型时,我使用了短语"Blob接口",并且"Blob对象"引用了一个Blob接口的单个实例。)

此外,使用Blob接口构造函数,可以使用这里接口将微小的Blob对象重新合并。

new Blob([blob, blob,...])

BlobBuilder 演示中可以找到一个示例,它加载一个MP3文件,然后将它的分解为不同的音频文件( 轨道),该文件将应用到自己的<音频> 标签,用于播放。 在演示中,用户可以在另一个 ORDER BY 合并的中重建 MP3,甚至将新的blob对象下载为 MP3。

注意:W3C已经摒弃了 BlobBuilder,支持 Blob。 两者产生相同的结果,但以不同的方式。 另外,webkit的BlobBuilder在 IE 和 Firefox 之间变化,因此最好先对Blob进行特征检测。

FileReader

FileReader 接口接受文件或者Blob对象,读取内容-File或者Blob对象仅引用本地计算机上存储的内容。 FileReader 可以优化为读取各种类型的文件例如 Text(UTF-8), ArrayBuffer(for binary) 或者base64数据 uri。 下面的示例演示如何使用 FileReader 获取文件的文本,给定blob对象实例。

var reader = new FileReader();
reader.onload = function(e){
 console.log(e.target.result);
}
reader.readAsText(blob);

类似地,你可以使用最适合 file: readAsArrayBuffer (。适用于大型二进制文件的处理) 或者 readAsDataURL ( 如果想快速将内容嵌入DOM对象,就像图像或者音频文件一样) 类型的读方法读取它的他内容。

FileReader 包含了多个事件侦听器: onerroronloadstartonabortonprogress ( 对于为大型文件创建进度条和捕获问题非常有用)。

URI方案

URI方案是文档中的代表对象。 资源可以是文件或者 Blob,它的对应的URL称为对象 URL。 给定Blob或者文件引用,可以使用 createObjectURL 创建对象 URL。 例如:

var objecturl = window.URL.createObjectURL(blob)

返回引用资源对象的URL,如"blob:http%3A//test.com/666e6730-f45c-47c1-8012-ccc706f17191".

如果可以在图像标记的src上放置典型 URI,则可以将这里字符串放置在任何位置。 对象资源持久化了文档,所以刷新页面,它就消失了。

FileSaver

FileSaver 接口公开了将blob写入用户目录下载的方法。 实现是相当简洁和简单的:

window.saveAs(blob, "filename")

但是,当前没有一个浏览器具有这里属性。 只有 IE 10支持一个简单的替代方案: navigator.msSaveOrOpenBlob 以及 navigator.msSaveBlob。 但如你所见,有一个垫片可以创建类似的功能,尽管没有一个平滑的用户体验。

所以这是一个相当低级别的螺母和 Bolts 关于文件 API,这是一个抽象概念的摘要。 不过别担心,这是一个烹饪课,用来把这些成分转化成你可以吃的东西。

加入聚会并构建一个示例

我以为我会打扮为( 图 1 ),并创建我自己的小照片操纵工具,在 http://adodson.com/graffiti。 检查一下,从你的文件系统中选择一个图像,在屏幕上重写,然后使用文件 api (。添加一些画布方法和指针事件) 下载作品。

图 1.涂鸦文件API应用程序

实现涂鸦应用

即使用花哨的图片,这个应用也有一个相当简单的前提:

  • 使用 File + FileListFileReader 选择一个图像作为背景。
  • 将图像装入画布标签并使用 HTML5 Canvas API操作图像。
  • 使用 Blob ( 或者 BlobBuilder )。( 或者 saveBlob ) 或者带有对象url的锚点标记 hack 下载新图像。

步骤 1: 选择文件

用户可以通过多种方式为此应用程序选择图像。

  • 使用表单输入选取文件
  • 拖放文件
  • 从剪贴板复制并粘贴文件

这些方法将它的侦听器连接到一个名为 readFile()的自定义函数中,使用 FileReader 实例提取文件数据。 下面是函数的代码。

// readFile, loads File Objects (which are also images) into our Canvas// @param File Objectfunction readFile(file){
 // Create a new FileReader Objectvar reader = new FileReader();
 // Set an onload handler because we load files into it asynchronously reader.onload = function(e){
 // The response contains the Data-Uri, which we can then load into the canvas applyDataUrlToCanvas( reader.result );
 };
 reader.reaAsDataURL(file);
}

这里,readFile 接受文件引用( 稍后显示) 并创建 FileReader 对象的新实例。 这里函数将数据作为 DataURL 读取,但也可以将数据作为二进制文件读取,也可以作为 ArrayBuffer 读取。

要将函数连接起来,使用文件引用作为参数,通过以前提到的方法之一。

使用表单输入选取文件

当前 FileAPI 不( 唉唉) 当前定义用于触发文件选择的本机方法。 但是,使用 type=file的旧可信表单输入很好地完成了任务:

<input type="file" name="picture" accept="image/png, image/jpeg"/>

像表单输入元素一样粗糙,它具有一些新的附加属性,这些属性是完美的。

接受属性提示可以接受的文件类型。 在这个例子中,是png和 jpeg。 它被留给设备来处理这个相应的( 例如 Windows 默认打开用户的图片库,并且只显示这些类型的文件)。

用户可以在一个步骤中选择一个或者多个文件,从而使多个标签。

接下来,需要将事件侦听器绑定到表单输入的更改事件,以便选择的用户能够自动触发 readFile:

document.querySelector('input[name=picture]').onchange = function(e){
 readFile(e.target.files[0]);
}

这里代码只接受第一个用户选择的文件( 无论是否使用了多重属性),然后调用 readFile,将该文件作为第一个参数传递。

输入小样式

这里显示的表单输入框并不真正符合我的美观,或者是你的。 所以,将它的定位在你选择的另一个元素上,不透明度为零( 但是要准备好它有固定的宽度,这可能会干扰其他元素)。 或者更复杂一点: 在屏幕上定位的输入框中调度自定义单击事件。 在这里阅读更多关于这个讨论的内容。

拖放文件

文件可以从文件资源管理器中拖动,并在表单输入 hack 中使用类似的事件模型。 当用户在画布上释放图像时发生"放置"事件。 事件包含名为 dataTransfer的属性,它有一个名为files的子属性。 在下面的代码中,e.dataTransfer.filesFileList ( 如上所述,FileList 包含一个文件引用列表)的一个实例,第一个文件项是 readFile的参数。 在 webkit,Firefox 和 IE 10中支持这一点。 下面是一个示例:

// stop FireFox from replacing the whole page with the file.canvas.ondragover = function () { returnfalse; };// Add drop handlercanvas.ondrop = function (e) {
 e.preventDefault(); e = e || window.event;
 var files = e.dataTransfer.files;
 if(files){
 readFile(files[0]);
 }
};

复制和粘贴文件数据

当用户将内容粘贴到文档中时,可以访问剪贴板数据。 这里数据可以是文本和图像的混合,而不是仅包含文件引用的文件列表,如表单输入控件或者拖动文件中的文件列表。

在代码 below 中遍历剪贴板数据,对与"*/图像"和"文件"相对应的类型和类型属性进行筛选。 使用 getAsFile() 获得项目实例的文件,该文件传递给 readFile

// paste Clipboard data// Well not all of it just the images.document.onpaste = function(e){
 e.preventDefault();
 if(e.clipboardData&&e.clipboardData.items){
 // pasted imagefor(var i=0, items = e.clipboardData.items;i<items.length;i++){
 if( items[i].kind==='file' && items[i].type.match(/^image/) ){
 readFile(items[i].getAsFile());
 break;
 }
 }
 }
 returnfalse;
};

这就是第一步。 我展示了三种获取 File 引用和将文件数据加载到文档中的方法。 我想知道是否有其它方法,所以请发送评论。

步骤 2: 将图像加载到画布上

步骤 1中的readFile 函数将生成的数据url移交给另一个自定义函数 applyDataUrlToCanvas。 这里函数在画布上绘制选定的图像。 以下是它的工作原理:

  • 查找图像的宽度和高度。
  • 查找图像的方向。
  • 在画布上画出最适合的图像。

查找宽度和高度

使用DOM图像函数,你可以轻松地确定任何图像的尺寸。 它是一种方便的技术,并执行如下操作:

var img = new Image();
img.onload = function(){
 // img.width// img.height}
img.src = dataURL;

查找方向

不幸的是,有一个宽度和高度,它是一个大的, 图片可以采取 portrait 模式,并保存在 landscape 中,或者图像可以被倒置。

在某些相机中,不保存图像的正确方向,而是在图像EXIF数据提供一个方向属性。 这可以从图像的二进制数据中读取。

将数据url转换为二进制字符串很简单:

var base64 = dataUrl.replace(/^.*?,/,'');var binary = atob(base64);

幸好,有一个开源 EXIF客户端库,由 Jacob Seidelin编写,它将把EXIF数据作为对象返回。 是的,awesome !

<scriptsrc="http://www.nihilogic.dk/labs/exif/exif.js"></script><scriptsrc="http://www.nihilogic.dk/labs/binaryajax/binaryajax.js"></script><script>var exif = EXIF.readFromBinaryFile(new BinaryFile(binary));//exif.Orientation</script>

Orientation属性是对应于四个旋转和四个翻转( 多余的)的范围 1 -8中的一个整数。

将图像绘制到画布

在发现方向值之后,你可以在画布上旋转和绘制。 如果你想查看我的算法,只需深入源代码,你可以在 http://adodson.com/graffiti/https://github.com/MrSwitch/graffiti 找到它。

步骤 3: 下载图像

最后一步是下载修改后的图像。 在 FileAPI 表中,可以使用Blob接口在客户端创建文件。 在 IE 10中包装新的msSaveBlob,或者在它的他现代浏览器中下载属性 hack ( 向上),并在客户端下载文件。

中自己尝试演示。 点击下载按钮。

演示使用 IE 10中的canvas.toBlob 方法获取当前在画布标记中绘制的图像的文件引用。 对于 Chrome 和 Firefox, toBlob shim 插件非常有用。

canvas.toBlob(function( file ){
 // Create a blob file,// then download with the FileSaver}

创建Blob对象实例的副本

我们可以跳过这个步骤,但是由于所有浏览器中的一个奇怪,不能直接从 canvas.toBlob 返回的Blob实例。 你需要复制它。

IE 10.Chrome 和 Firefox 中支持用于创建新Blob引用的BlobBuilder 接口。 但是这个接口已经被Blob构造器所取代,它现在支持有限的支持。

首先,shim 离开 BlobBuilder的供应商前缀:

// Shim the BlobBuilder with the vendor prefixeswindow.BlobBuilder || (window.BlobBuilder = window.MSBlobBuilder||window.MozBlobBuilder||window.WebKitBlobBuilder);

接下来,对代码进行验证并测试Blob构造函数。 否则,构建一个 BlobBuilder 以构建一个。 ( 最好将这些方法打包在 try-catch ) 当前 Chrome 浏览器的中的Blob是 buggy。 这是密码。

var blob;if('Blob'in window){
 try{
 // The new Blob interface blob = new Blob([file],{ "type" : "image/png"});
 catch(e){}
}if(!blob){
 try{
 // The deprecated BlobBuilder interfacevar bb = new BlobBuilder();
 bb.append( file ); 
 blob = bb.getBlob("image/png");
 }
 catch(e){}
}

使用FileSaver下载 Blob

FileSaver API还是目前任何浏览器的一个标准。 但是,在 IE 10中,可以使用 msSaveBlob 函数( 那真是太棒了),对 Chrome 和 Firefox 至少可以将它们证明为供应商前缀。 因此,saveAs 函数需要一些巨大的shimming:

window.saveAs || (window.saveAs == window.navigator.msSaveBlob || window.webkitSaveAs || window.mozSaveAs || window.msSaveAs /** || URL Download Hack **/ );

返回( 在 https://gist.github.com/3552985 完整描述。) shims使用我们新图像的对象URL来启动 FileSaver 接口。 对于支持zip标记上的下载属性的浏览器,shim 将href定义为对象 URL,然后调度click事件。 哦,我们编织的蜘蛛网。

最后,给定blob和文件 NAME,saveAs 方法启动下载:

var name = 'Graffiti.png';if(window.saveAs){
 // Move the builder object content to a blob and  window.saveAs(blob, name); 
}else{
 // Fallover, open as DataURL window.open(canvas.toDataURL());
}

如果 saveAs shim 不兼容,则 fallover 将打开一个带有base64数据url的新标签。 这在 IE 9中工作,但 IE 8只限于 32 KB的datauri长度。

结束语

如果你还没有使用过文件 API,我强烈建议你。 FileAPI为浏览器开发桌面像应用程序带来了巨大的潜力。 你可能需要对保存文件和覆盖现有文件的位置进行更多的控制。 但是现在,安全性一直在警告中,因这里你很不可以能很快看到这样的特性。 我们在本文中突出显示的是浏览器供应商的大量投资,不太可以能改变。 请不要引用我。

你可以使用 older dropfile.js 来支持 shim,用于 IE的,并创建一个base64数据 uri,并创建一个base64数据 uri,并为 FileSaver 创建一个。

这篇文章是由 Andrew Dodson写的。 Andrew是一个网络技术迷,他对 EcmaScript。HTML和CSS都很粗鲁。 Andrew热衷于编写跨平台网络应用程序。 他负责 curates BrowserExperiments.com 并贡献给 HTML5 跨浏览器 Polyfills以帮助他人。 当安德鲁不写漂亮的代码时,他喜欢在伦敦和悉尼之间的事件。 Andrew目前住在悉尼,担任自由开发者。

HTML5视频资源


文件  API  GET  Loaded  
相关文章