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

最近在看《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(){
//判断等待上传的文件列表是否为 0
if(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对象自己创建的,切不可自己修改.

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

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

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


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值