ajax异步文件上传原理解析

有一段时间没发文章了,明河手上项目太紧了,终于快临近发布了,偷闲跟大家分享下ajax异步文件上传原理,前段时间一直在捣鼓异步文件上传,也算颇有心得,以前也写过flash文件上传组件,有兴趣的朋友可以看 yijs.File,早期作品,代码比较粗糙,最近又写了二个异步文件上传组件,一个是基于iframe,一个是基于flash,都是基于KISSY1.2,日后会放出。言归正传,今天来谈下ajax异步文件上传的原理。
(PS:英文原文可以看 《Uploading Files with AJAX》)。
1.在demo中我们要实现的功能
  • 异步上传文件(支持多选上传)
  • 可以即时预览图片
2.通过这篇教程你将学会什么?
  • ajax异步文件上传的核心原理
  • 新的文件API:FileReader对象的用法;
  • FormData对象的用法(这是XMLHttpRequest2的内容)。

很遗憾的是IE对FileReader和FormData并不支持(包括IE9),所以文中的方案有兼容性问题,想要实现全兼容的文件上传(包括图片预览),还需要其他技巧,以后讲解明河完成的异步上传组件时会说明。
(PS:Opera目前不支持FormData对象,请在firefox和chrome下浏览demo。)

3.构建图片上传表单
  1. <form method="post" enctype="multipart/form-data"  action="upload.php">
  2.             <input type="file" name="images" id="images" multiple />
  3.             <button type="submit" id="btn">Upload Files!</button>
  4.         </form>

想要实现异步文件上传的第一个关键步骤,给form增加enctype=”multipart/form-data”属性,这个属性非常关键,缺少这个属性,将直接提交表单。
action属性指向处理文件上传数据的服务器端路径。
多选上传的关键是在上传框上加multiple属性。

4.upload.php

我们先来看服务器端处理文件脚本:

  1. <?php
  2.  
  3. foreach ($_FILES["images"]["error"] as $key => $error) {
  4.     if ($error == UPLOAD_ERR_OK) {
  5.         $name = $_FILES["images"]["name"][$key];
  6.         move_uploaded_file( $_FILES["images"]["tmp_name"][$key], "uploads/" . $_FILES['images']['name'][$key]);
  7.     }
  8. }
  9. echo "<h2>文件成功上传!</h2>";

这段php脚本做了非常多的简化,比如缺少文件大小限制、文件去重、用户限制等一系列安全处理。
$_FILES这个关联数组存放着文件数据,是处理的关键,有不清楚的朋友可以看php手册,这里不再累述,毕竟不是本文讲解重点。

5.监听上传框的change事件
  1. var input = document.getElementById("images");
  2. input.addEventListener("change", function (evt) {
  3.     var files = this.files;
  4. })

留意这里的this.files,files数组将存储你上传的文件信息,即使只上传1张图片,也是数组形式出现。

6.利用FileReader将图片显示到页面上

关于FileReader,w3c有非常详细的说明,传送门点此

  1. //遍历文件
  2. for ( ; i < len; i++ ) {
  3.     file = this.files[i];
  4.     //文件类型为图片
  5.     if (!!file.type.match(/image.*/)) {
  6.         //浏览器支持FileReader对象
  7.         if ( window.FileReader ) {
  8.             reader = new FileReader();
  9.             //监听文件读取结束后事件
  10.             reader.onloadend = function (e) {
  11.                 //将图片添加到显示列表
  12.                 showUploadedItem(e.target.result, file.fileName);
  13.             };
  14.             //读取文件
  15.             reader.readAsDataURL(file);
  16.         }
  17.         //将文件数据添加到FormData对象内
  18.         if (formdata) {
  19.             formdata.append("images[]", file);
  20.         }
  21.     }   
  22. }

首先需要判断下文件类型,file.type.match(/image.*/),如果是图片,file.type值会类似“image/jpeg”的形式。
接下来实例化FileReader读取文件。

  1. reader = new FileReader();
  2.             //监听文件读取结束后事件
  3.             reader.onloadend = function (e) {
  4.                 //将图片添加到显示列表
  5.                 showUploadedItem(e.target.result, file.fileName);
  6.             };
  7.             //读取文件
  8.             reader.readAsDataURL(file);

FileReader有6个事件( onloadstart、onprogress、onload、onabort、 onerror、onloadend),onloadend监听读取完毕事件,我们需要读取结束后把图片打印到页面。
留意e.target.result,result包含图片数据
最后来看下showUploadedItem函数:

  1. //显示上传图片
  2.     function showUploadedItem (source) {
  3.           var list = document.getElementById("image-list"),
  4.               li   = document.createElement("li"),
  5.               img  = document.createElement("img");
  6.           img.src = source;
  7.           li.appendChild(img);
  8.         list.appendChild(li);
  9.     }

非常简单,将img元素添加到li元素,然后li添加到ul即可。

7.ajax发送FormData数据
  1. //遍历文件
  2.         for ( ; i < len; i++ ) {
  3.             file = this.files[i];
  4.                 //将文件数据添加到FormData对象内
  5.             if (formdata) {
  6.             formdata.append("images[]", file);
  7.             }
  8.         }

将文件信息添加到formdata。

  1. //发送ajax请求,存储文件(传递FormData对象过去)
  2. if (formdata) {
  3.     $.ajax({
  4.         url: "upload.php",
  5.         type: "POST",
  6.         data: formdata,
  7.         processData: false,
  8.         contentType: false,
  9.         success: function (res) {
  10.             //将上传成功后的提示打印到页面
  11.             document.getElementById("response").innerHTML = res;
  12.         }
  13.     });
  14. }

发送异步请求将数据传给upload.php处理。这里使用jquery的ajax方法。


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值