【javascript】脚本操作HTTP请求技术Ajax-3 (单个文件上传)

来源:互联网 发布:常用的网络命令有哪些 编辑:程序博客网 时间:2024/04/29 13:02

最近在看《javascript权威指南》的时候,发现它在Ajax技术上讲解了关于javascript上传文件的内容。这也是博主在多年前的一个困扰,曾经解决的办法就是借用别人的js控件,因此对这个技术理解甚少。当然,解决异步文件上传的方式有许多种,比如利用flash插件,或者是嵌入iframe元素,等等。接下来就开始介绍我们如何通过Ajax技术进行文件上传。


首先,支持文件上传的浏览器是有所限制的。其关键在于浏览器是否支持XMLHttpRequest level 2 的 API,在这里会有一些对象需要介绍一下。

  1.  File对象, 这个对象不能通过构造函数生成,只能从 input file 控件的 files[]列表获取.
  2.  FormData对象,这个对象就是form表单的载体。

接下来我们先制作一个简单的html页面,其中有两个关键元素

<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>文件上传</title>    <script type="text/javascript" src="/js/ajax.js"></script></head><body><input type="file" name="file" id="file" /><button id="go">提交</button></body></html>

然后我们发现,该页面存在一个ajax.js脚本. 这个脚本主要就是为我们提供一些ajax的方法

function  createXHR(){    if( typeof  XMLHttpRequest != "undefined"){        return  new XMLHttpRequest();    }    if(typeof ActiveXobject == "undefined"){        throw new Error(" not support ");    }    //判断是否为 IE    if(typeof arguments.callee.activeString != "string"){        var versions = ["MSXML2.XMLHttp.6.0","MSXML2.XMLHttp3.0","MSXML2.XMLHttp"],            i,len;        for (var i = 0;i<versions.length;i++) {            try{                    new ActiveXobject(versions[i]);                    arguments.callee.activeString=versions[i];                    break;            }catch(ex){                //  no action            }        };    }    return  new ActiveXobject(arguments.callee.activeString);}/***文件表单上传**@param  {String}    url*@param  {FormData}  form*@param  {Function}  callback*/function formData(url,form,callback){    var xhr = createXHR();    xhr.open("POST",url);    xhr.onreadystatechange = function(){        if(xhr.readyState == 4 && (xhr.status == 200)){            callback(xhr);        }    }    xhr.send(form);}

只凭这些是不能完成文件上传的.我们在html页面中添加一些脚本代码,最好是在body元素的后部添加script脚本.

function $(id){return document.getElementById(id);} //简化通过id获取元素节点var filedata =[];//生成一个空数组// 为file控件添加一个change事件$("file").addEventListener("change",function(e){var file = this.files[0]; //默认获取第一个文件  返回的是一个File对象//读取文件的基本属性var data =  { name : file.name,  //文件的名称              size : file.size,  //文件的大小              type : file.type || "",  //文件的类型 如果没有文件类型则为空              id   : (file.lastModifiedDate + "").replace(/\W/g, '') + this.size + this.type.replace(/\W/g, '')  //生成文件唯一id               };// 将文件名的id存入数组filedata中filedata.push(data.id);// 扩展filedata数组,通过文件唯一id 保存文件的基本信息 以及 File文件对象filedata[data.id] = {info:data,file:file};console.log(filedata);},false);//为按钮添加一个click事件$("go").addEventListener("click",function(){//判断等待上传的文件列表是否为 0if(filedata.length <= 0 ){    alert('请选择至少一个文件');    return;}var id   = filedata[0];var data = filedata[id];// form表单对象var form = new FormData();// 请求url地址var url  ="http://localhost/demo/uploadFile";// 添加若干参数 第一个参数为参数名,第二个参数为参数值form.append("name",data.info.name);form.append("type",data.info.type);form.append("fileid",id);// 添加文件对象,将文件以字节流的方式作为请求主体.form.append("file",data.file);//调用写好的函数formData(url,form,function(res){    //请求-响应成功    //删除上传成功的文件对象    delete filedata[id];    filedata.shift();    console.log(res.responseText);});},false);//判断浏览器是否支持脚本上传功能if(FormData == undefined){    throw new Error("浏览器不支持");}

这里并没有做一些比较好看的css效果,这样是为了简化过程.我们只要看到结果就可以了.写完了前端的代码.我们该考虑后端如何写.

首先我们得确认后端的配置是否允许文件上传的功能,我的服务端代码是用PHP写的,所有要修改一下php.ini 的一些配置,至于如何修改可以查看网络的资源,搜索关键字: php 文件上传 配置修改.

在确保这些都没有问题的情况下,我来给大家展示php的端代码.

<?php$filename = $_POST['name'];$fileId   = $_POST['fileid'];$postfix  = explode(".",$filename); //获取后缀$postfix  = empty($postfix[1])?"":".".$postfix[1];// public_path() 返回的是一个绝对的路径 可自己定义$filepath = public_path().'/uploads/'.$fileId.$postfix;//文件写入file_put_contents($filepath, file_get_contents($_FILES["file"]["tmp_name"]), FILE_APPEND);echo json_encode(array("rs"=>"success","path"=>"/uploads/".$fileId.$postfix));exit;?>

下面是测试截图- Firefox 浏览器

我们选择一个文件后,会触发 file元素的onchange事件

上面是 filedata 的一些属性值。

然后我们点击按钮上传后,查看一下我们的请求响应头部

这个请求头部类型为我们的FormData对象自己创建的,切不可自己修改.

这样我们检测一下目标路径.

发现图片确实已经上传成功。因此,简单的异步上传文件的例子就说到这里,我们可以发现,还可以进一步完善这个例子,例如添加一个进度监听事件,查看文件目前上传的大小情况以及终止或暂停文件上传等等。要丰富这个功能的话,确实需要点能力。不过,我会慢慢的学习并且做一些案例来讲解。

最后给大家推荐一个百度团队开发的文件上传组件。点击打开链接


0 0
原创粉丝点击