php+jquery+ajax异步批量上传图片文件,并显示进度条

简介:

通过jquery的ajax异步上传文件,使用FormData 对象提交数据,使用xhr显示上传进度条。
主要用于:批量上传图片,上传文件数据,也可用于异步提交数据,而独立于表单使用。
这篇文章主要讲述,批量上传txt的文件,图片类似。

  1. html的使用要求,from必须有属性:enctype=“multipart/form-data” ,如果批量多个文件上传必须有:multiple=“multiple”,accept=“text/plain” 或 accept=“image/*”
<form action='sc.php' method="post" enctype="multipart/form-data" >
	<input type="file" name="ycfile" id="ycfile"  multiple="multiple" accept="text/plain"/>
	<input type="button" value="上传" id="shangchuan"/>
	<div style="width:600px;height:auto;border:1px solid red;" id="zhanshi">
	</div>
</form>

2.导入jquery库,写一个input的change事件,申明一个全局变量i,每张上传文件对应一个数字,一个全局变量data,格式为formdata对象,使用formdata提交数据。
此处可以使用append追加数据,但是append我不知道怎么删除列表中的单独一个元素

     var i=0;
		var data = new FormData();
		$("#ycfile").change(function(){
			var files = $(this).prop('files');
			$.each(files,function(index,value){
			 // 使用formdata的set函数,对上传的文件进行保存
				data.set('myfile_'+i, value);
				var html = '
+i+'">+i+'">'+value.name+'+i+'">0%
+i+'" style="background:#428bca;width:0px;height:10px" >
+i+'" class="progresssc" scid="'+i+'">删除
'
; i = i+1; //在此处可以做上传图片预览,因为我上传的是txt文件,所以只是展示,做一个删除功能 $("#zhanshi").append(html); }) });

3.点击上传按钮,对每个formdata中的对象逐个异步上传,注意点击按钮直接提交表单。

formdata知识点:https://developer.mozilla.org/zh-CN/docs/Web/API/FormData/values

$("#shangchuan").click(function(){
	if (!data) {
		alert("请上传文件");
		return false;
	}
	var upload_data = data;
	//点击上传就清空data数据
	data = new FormData();
	for (var key of upload_data.keys()) {
		if(key && upload_data.get(key)) {
			shangchuan(key,upload_data.get(key))
		}
	}
});

4.异步进行上传文件数据,然后显示进度条

function shangchuan(key,value)
{
	//截图key后面的数字
	var index = key.split("_").pop();
	var ext = value.name.split(".").pop();
	console.log(key+"来了");
	//console.log(value);
	if(ext !== "txt") {
		$("#hezi_"+index).append("上传失败:上传的文件类型不正确");
		return key;
	}
	if(value.type !== "text/plain") {
		$("#hezi_"+index).append("上传失败:上传的文件类型不正确");
		return key;
	}
	if ((value.size/1024)>(10*1024)) {
		$("#hezi_"+index).append("上传失败:上传的文件大小为10M");
		return key;
	}
	var formData = new FormData();
	formData.append("wenjian",value)
	$.ajax({
		url: 'sc.php',
		type: 'POST',
		data: formData,
		cache: false,
		processData: false,
		contentType: false,
		dataType:'json',
		xhr: function () {
			var xhr = new XMLHttpRequest();
			xhr.upload.addEventListener('progress', function (e) {
				//外部资源加载过程中触发,默认500毫秒。
				//loaded代表上传了多少
				//total代表总数为多少
				var progressRate = Math.round((e.loaded / e.total) * 100,-2) + '%';

				//console.log(progressRate);
				//通过设置进度条的宽度达到效果
				$("#percent_"+index).html(progressRate)
				$("#progressnumber_"+index).css("width",progressRate);
			})
			xhr.upload.addEventListener('load', function (e) {
				//外部资源加载成功时触发。如果后台处理时间过长,可以在此提示“后台正在处理请稍等”
			})
			return xhr;
		},
		success: function (res) {
			if(res.status=='fail') {
				console.log("失败了");
				$("#hezi_"+index).append("上传失败:"+ res.msg +"");
			}else if(res.status=='success'){
				$("#shanchu_"+index).remove();
				$("#hezi_"+index).children('.shibai_tishi').remove();
				console.log(res.data);
				//可以把返回的上传路径展示在页面中
			}else {
				$("#hezi_"+index).append("上传失败:未知原因");
			}
			return key;
		}
	});
}

5.对上传失败的文件进行删除,因为展示代码是jquery追加的,所以需要用on绑定事件
此处大家可以考虑一下,怎么使用FormData.delete(),删除append 追加的指定任意元素

$("#zhanshi").on("click",".progresssc",function () {
	//删除准备上传的文件
	var id = $(this).attr("scid")
	data.delete("myfile_"+id);
	$(this).parent("div").remove();
});

6.php代码处理上传的文件,返回json格式的数据
此处有个问题,就是上传的文件超过php的max_upload设置,直接报错了,这样ajax就没法判返回结果了,要不然再处理结果的时候写个else ,我屏蔽以后没效果,不知道是不是我本地环境的问题.

 exit(json_encode(['status'=>'fail',"msg"=>"后缀不正确","data"=>""]));
 exit(json_encode(['status'=>'success',"msg"=>"成功","data"=>trim($upload_path.$file_name)]));

7.全部源码

<!DOCTYPE html>
<head>
	<meta charset=utf-8><meta name=referrer content=always><meta http-equiv=x-dns-prefetch-control content=on><meta http-equiv=X-UA-Compatible content="IE=edge,chrome=1">
	<script type="text/javascript" src="jquery-1.7.2.min.js"></script>
	<title>上传</title>
</head>
<body>
<form action='sc.php' method="post" enctype="multipart/form-data" >
	<input type="file" name="ycfile" id="ycfile"  multiple="multiple" accept="text/plain"/>
	<input type="button" value="上传" id="shangchuan"/>
	<div style="width:600px;height:auto;border:1px solid red;" id="zhanshi">
	</div>
</form>
<script>
	$(function(){
		var i=0;
		var data = new FormData();
		$("#ycfile").change(function(){
			var files = $(this).prop('files');
			$.each(files,function(index,value){
				data.set('myfile_'+i, value);
				var html = '
+i+'">+i+'">'+value.name+'+i+'">0%
+i+'" style="background:#428bca;width:0px;height:10px" >
+i+'" class="progresssc" scid="'+i+'">删除
'
; i = i+1; $("#zhanshi").append(html); }) }); $("#zhanshi").on("click",".progresssc",function () { //删除准备上传的文件 var id = $(this).attr("scid") data.delete("myfile_"+id); $(this).parent("div").remove(); }); function shangchuan(key,value) { //截图key后面的数字 var index = key.split("_").pop(); var ext = value.name.split(".").pop(); console.log(key+"来了"); //console.log(value); if(ext !== "txt") { $("#hezi_"+index).append("上传失败:上传的文件类型不正确"); return key; } if(value.type !== "text/plain") { $("#hezi_"+index).append("上传失败:上传的文件类型不正确"); return key; } if ((value.size/1024)>(10*1024)) { $("#hezi_"+index).append("上传失败:上传的文件大小为10M"); return key; } var formData = new FormData(); formData.append("wenjian",value) $.ajax({ url: 'sc.php', type: 'POST', data: formData, cache: false, processData: false, contentType: false, dataType:'json', xhr: function () { var xhr = new XMLHttpRequest(); xhr.upload.addEventListener('progress', function (e) { //外部资源加载过程中触发,默认500毫秒。 //loaded代表上传了多少 //total代表总数为多少 var progressRate = Math.round((e.loaded / e.total) * 100,-2) + '%'; //console.log(progressRate); //通过设置进度条的宽度达到效果 $("#percent_"+index).html(progressRate) $("#progressnumber_"+index).css("width",progressRate); }) xhr.upload.addEventListener('load', function (e) { //外部资源加载成功时触发。如果后台处理时间过长,可以在此提示“后台正在处理请稍等” }) return xhr; }, success: function (res) { if(res.status=='fail') { console.log("失败了"); $("#hezi_"+index).append("上传失败:"+ res.msg +""); }else if(res.status=='success'){ $("#shanchu_"+index).remove(); $("#hezi_"+index).children('.shibai_tishi').remove(); console.log(res.data); //可以把返回的上传路径展示在页面中 }else { $("#hezi_"+index).append("上传失败:未知原因"); } return key; } }); } $("#shangchuan").click(function(){ if (!data) { alert("请上传文件"); return false; } var upload_data = data; //点击上传就清空data数据 data = new FormData(); for (var key of upload_data.keys()) { if(key && upload_data.get(key)) { shangchuan(key,upload_data.get(key)) } } }); }) </script> </body> </html>
<?php

ini_set('display_errors', 0);
error_reporting(E_ALL^E_NOTICE^E_WARNING);
$field = "wenjian";
if(!isset($_FILES[$field])) {
    exit(json_encode(['status'=>'fail',"msg"=>"请上传文件","data"=>""]));
}

if ($_FILES[$field]['tmp_name'])
{
    $error = ( ! isset($_FILES[$field]['error'])) ? 4 : $_FILES[$field]['error'];
    switch($error)
    {
        case 1:	// UPLOAD_ERR_INI_SIZE
            exit(json_encode(['status'=>'fail',"msg"=>"上传的文件超过限制","data"=>""]));
            break;
        case 2: // UPLOAD_ERR_FORM_SIZE
            exit(json_encode(['status'=>'fail',"msg"=>"上传的文件超过表单限制","data"=>""]));
            break;
        case 3: // UPLOAD_ERR_PARTIAL
            exit(json_encode(['status'=>'fail',"msg"=>"对不起,文件上传不完整!","data"=>""]));
            break;
        case 4: // UPLOAD_ERR_NO_FILE
            exit(json_encode(['status'=>'fail',"msg"=>"请选择上传的文件!","data"=>""]));
            break;
        case 6: // UPLOAD_ERR_NO_TMP_DIR
            exit(json_encode(['status'=>'fail',"msg"=>"文件上传没有临时目录!","data"=>""]));
            break;
        case 7: // UPLOAD_ERR_CANT_WRITE
            exit(json_encode(['status'=>'fail',"msg"=>"对不起,文件写入失败!","data"=>""]));
            break;
        default :
            break;
    }


    $ext = explode('.', $_FILES[$field]['name']);
    $ext = end($ext);
    $ext = strtolower($ext);
    if(!in_array($ext,array('txt')))
    {
        exit(json_encode(['status'=>'fail',"msg"=>"后缀不正确","data"=>""]));
    }

    $file_size = round($_FILES[$field]['size']/1024,2); //单位kb
    if($file_size>10240)
    {
        //10M
        exit(json_encode(['status'=>'fail',"msg"=>"文件大小请限制在10M以内","data"=>""]));
    }
    $upload_path = "./upload/";
    $file_name = uniqid().rand(1,99999).time().'.'.$ext;

    //开始上传我们将尝试使用副本()。如果该操作失败 我们将使用函数()。这两个应该之一 在大多数环境中可靠地工作
    if ( ! copy($_FILES[$field]['tmp_name'], $upload_path.$file_name))
    {
        if ( ! move_uploaded_file($_FILES[$field]['tmp_name'], $upload_path.$file_name))
        {
            exit(json_encode(['status'=>'fail',"msg"=>"上传失败了。","data"=>""]));
        }
    }
    //因为我这里读取txt文件内容,不需要保存文件就直接删除了
    //unlink($upload_path.$file_name);
    exit(json_encode(['status'=>'success',"msg"=>"成功","data"=>trim($upload_path.$file_name)]));

}
exit(json_encode(['status'=>'fail',"msg"=>"请上传文件","data"=>""]));
?>

你可能感兴趣的:(JavaScript,ajax,jquery,php,html5)