手动实现完全加强版js文件上传到php

编程入门 行业动态 更新时间:2024-10-12 05:53:39

手动实现完全<a href=https://www.elefans.com/category/jswz/34/1756067.html style=加强版js文件上传到php"/>

手动实现完全加强版js文件上传到php

最近做项目,要用到js上传大文件插件,网上找了很多上传插件,最后试着用了jquery file upload插件,然后确实很简单就可以上传了,demo也可以直接用,但是具体的实现逻辑本封装了,而我木有去看js源码(有点懒,源码太多了),而且php服务器的源码也太大,完全看不过来,于是自己搜了搜ajax文件上传的基本逻辑,结合一些资料,自己鼓捣了一个简单文件上传插件,麻雀虽小,但是五脏俱全。


先说说ajax上传文件的基本逻辑:

首先是选择文件,使用fileinput标签,会得到一个待上传文件的队列:file_list
然后,选择提交(submit)表单,或者把文件队列加到formData里,作为ajax的data部分,文件会先被上传到指定服务器的文件缓存文件夹,存为缓存文件(外部不可访问),缓存文件夹是服务器配置的,例如php是在php.in里面配置缓存文件夹。
一直到前一步,服务器都是默认操作,直到客户端进度条走完,也就是上传完毕,自己写的服务器脚本开始运行,指定的服务器脚本会获取ajax提交的文件信息和缓存的文件路径,这时候,我们就可以在脚本里把缓存文件存到自己文件夹下,存为自定义的文件名,
然后,服务器返回客户端json数据,于是客户端ajax异步调用完成,调用回调函数处理服务器返回数据


1、首先:html基本元素

<div class="container">
<form action="uploadtemp.php" method="post" enctype="multipart/form-data"><span class="btn btn-success fileinput-button"><i class="glyphicon glyphicon-plus"></i><span>Add files...</span><!-- The file input field used as target for the file upload widget --><input id="fileupload2" type="file" name="file_list[]" multiple></span>
</form><div style="width: 100%;float:left"><ul id="upload_file_list"  class="file_list_ul"><li class="file_list_li"><img class="image_min_preview" src="=50&bg=grey&txt=实例&w=300&h=300"><div class="file_list_file_name">I am file name</div><div class="file_list_file_msg">This is a return msg</div><button class="file_list_file_cancel_btn btn btn-primary">This is cancel btn</button></li></ul></div><button id="start_upload_file_list" class="btn btn-primary" >开始上传</button><button id="abort_upload_file_list" class="btn btn-primary" >取消上传</button><div style="margin:10px 0px"><div id="file_list_progress" class="_progress"><div class="_progress-bar"></div></div></div><div style="width: 100%;float:left"><ul id="download_file_list"  class="file_list_ul"><li class="file_list_li"><img class="image_min_preview" src="=50&bg=grey&txt=实例&w=300&h=300"><div class="file_list_file_name">I am download file name</div><div class="file_list_file_msg">This is a return msg</div><button class="file_list_file_cancel_btn btn btn-primary">This is cancel btn</button></li></ul></div>
</div>



因为我用了bootstrap,只是为了界面好看点,必须元素就三个 #fileupload2文件选择控件,然后上传队列预览div,上传按钮,取消上传按钮,进度条,还有下载队列div(上传后由服务器返回)

2、获取上传文件队列

因为我们使用ajax上传,所以使用input file的change事件,每次获取选择的文件,并保存到file_list队列
$("#fileupload2").change(function(){var $this=$(this);var files=$this[0].files;//需要计算上传的数据总量和数量,限制上传大小for(index in files){//在list中列出所有待上传文件\if(!isEmptyObject(files[index])){//添加到上传队列if($.inArray(files[index].name,file_list.file_name_list)!=-1){alert("this file : "+files[index].name+" is already in the file list");continue;}file_list.push(files[index]);
		//该函数用于在上传队列预览div里创建预览条目createFilePreview(files[index], $("#upload_file_list"));}}
$("#fileupload2").val('');


3、给上传按钮绑定点击事件
点击按钮即实现文件上传:


$("#start_upload_file_list").click(function(){//alert("max_upload_file_num:"+max_upload_file_num);//alert("max_upload_file_total_size:"+max_upload_file_total_size);var $this=$(this);$('#file_list_progress .progress-bar').css('width','0%');//设置按钮不可用$("li.file_list_li button").addClass("disabled").text("上传后不可用");//提交上传var formdata=new FormData();for(index in file_list){if(!isEmptyObject(file_list[index])){file_num=file_num+1;file_total_size=file_total_size+file_list[index].size;formdata.append(file_list_name,file_list[index]);}}//p判定是否满足上传限制if(file_total_size>max_upload_file_total_size || file_num>max_upload_file_num){alert("上传文件数不能超过"+max_upload_file_num+"\r\n"+"上传文件总大小不能超过"+max_upload_file_total_size_M+"M"+"\r\n"+"您的上传文件错处,请重新选择上传队列");return;}$this.button('loading');//ajax请求var upload_ajax_request=$.ajax({url: 'uploadtemp.php',type: 'POST',data: formdata,cache: false,processData: false,contentType: false,//这里我们先拿到jQuery产生的 XMLHttpRequest对象,为其增加 progress 事件绑定,然后再返回交给ajax使用xhr: function(){var xhr = $.ajaxSettings.xhr();if(onprogress && xhr.upload) {xhr.upload.addEventListener("progress" , onprogress, false);return xhr;}},success:function(data,status){//alert(data);var obj;try {obj = JSON.parse(data);}catch (e){alert("error:"+data);//$this.button('上传出错');}//ShowObjProperty(obj);for(file_name in obj){//indexif(obj[file_name].success){//上传成功//上传成功从文件上传队列移除$("li[name='upload_"+file_name+"']").slideUp('slow',function(){$("li[name='upload_"+file_name+"']").remove();});createFileUploadSuccessView(obj[file_name],$("#download_file_list"));//从队列里面删除返回成功的filevar index=$.inArray(file_name,file_list.file_name_list);if(index!=-1){file_list.file_name_list.splice(index,1);file_list.splice(index,1);}$("li[name='upload_"+file_name+"'] div[name='msg']").html("<a href='"+obj[file_name].url+"'><font color='green'>上传成功</font></a>").fadeIn();}else{//上传失败$("li[name='upload_"+file_name+"'] div[name='msg']").html("<font color='color'>"+obj[file_name].msg+"</font>").fadeIn();$("li[name='upload_"+file_name+"'] button").removeClass("disabled").text("移除");}}if(file_list.length==0){$("#file_list_progress").slideUp();$("#start_upload_file_list").slideUp();}$("#abort_upload_file_list").fadeOut();$this.button('reset');//alert(status);},error:function(xhr,error,exception){alert(error);},complete:function(XHR, TS){},beforeSend:function(xhr){}});//显示 取消上穿 按钮$("#abort_upload_file_list").fadeIn().click(function(){upload_ajax_request.abort();$("#abort_upload_file_list").fadeOut();$this.button('reset');});});
注意,在点击确定上传后,在将上传队列文件加载到formData对象里,再将formData作为数据data上传到服务器端 也可以看到ajax的回调函数可以处理服务器返回值

4、服务器端的实现:

简单地实现php的文件上传就可以了,注意规定好前后台通信的json格式就好了
<?php
/*** Created by PhpStorm.* User: GongCheng* Date: 2017/03/16* Time: 03:32 PM*/
require_once("php/strTools.php");
$file_name='file_list';
if(isset($_FILES[$file_name])) {//echo "files2<br/>";$count = count($_FILES[$file_name]['name']);$return = array();for($i=0;$i<$count;$i++){$file=array('name'=>$_FILES[$file_name]['name'][$i],'type'=>$_FILES[$file_name]['type'][$i],'size'=>$_FILES[$file_name]['size'][$i],'tmp_name'=>$_FILES[$file_name]['tmp_name'][$i],'error'=>$_FILES[$file_name]['error'][$i],);//var_dump($file);$return[$file['name']]=jquery_save_img($file);//echo $file['name']." : <br/>";//var_dump($return[$file['name']]);}//echo json_encode($return);echo ch_json_encode($return);//echo json_last_error();//var_dump($return);//jquery_save_img($file_name);
}else{echo json_encode(array(false=>array('msg'=>'can not find file_list name')));
}
function jquery_save_img($file)
{$arrType=array('image/jpg','image/gif','image/png','image/bmp','image/pjpeg','image/jpeg','application/octet-stream','application/x-zip-compressed','video/mp4');$max_size='500000000000';      // 最大文件限制(单位:byte)$upfile='./upload_files'; //图片目录路径//$file=$_FILES[$file_name];//if(isset($_FILES["file"])/*echo 'filename:'.$file['tmp_name'].';<br />';echo 'size:'.$file['size'].';<br />';echo 'type:'.$file['type'].';<br />';echo 'name:'.$file['name'].';<br />';*/if($_SERVER['REQUEST_METHOD']=='POST'){ //判断提交方式是否为POST//clearstatcache();//$file['tmp_name'] = str_replace('', '//', $file['tmp_name']);if(!is_uploaded_file($file['tmp_name'])){ //判断上传文件是否存在//echo $file['tmp_name']." -> ".$upfile."/".mb_convert_encoding($file['name'],"gbk", "utf-8");;return (array('success'=>false,'msg'=>'文件不存在!'));}//echo "我是:haha";if($file['size']>$max_size){  //判断文件大小是否大于500000字节return  (array('success'=>false,'msg'=>'上传文件太大!'));}if(!in_array($file['type'],$arrType)){  //判断图片文件的格式return  (array('success'=>false,'msg'=>'上传文件格式不对!xxx:'.$file['type']));}if(!file_exists($upfile)){  // 判断存放文件目录是否存在mkdir($upfile,0777,true);}$imageSize=getimagesize($file['tmp_name']);$img=$imageSize[0].'*'.$imageSize[1];$fname=$file['name'];$ftype=explode('.',$fname);//因为在windows下为gbk编码,而php默认utf8编码,如果不转换编码,在中文时容易出现编码错误而不能存储//mb_convert_encoding函数:转换编码//mb_convert_encoding('待转化字符串','想要转换的编码','本身的编码')$picName=$upfile."/".mb_convert_encoding($fname,"gbk", "utf-8");//echo $picName;if(file_exists($picName)){return (array('success'=>false,'msg'=>'同文件名已存在!'.$fname));}if(!move_uploaded_file($file['tmp_name'],$picName)){return  (array('success'=>false,'msg'=>'移动文件出错!'.$picName));//echo "<font color='#FF0000'>移动文件出错!</font>";}else{/*echo "<font color='#FF0000'>图片文件上传成功!</font><br/>";echo "<font color='#0000FF'>图片大小:$img</font><br/>";echo "图片预览:<br><div style='border:#F00 1px solid; width:200px;height:200px'><img src=\"".$picName."\" width=200px height=200px>".$fname."</div>";*/return (array('success'=>true,'url'=>$upfile."/".$fname,'name'=>$fname,'size'=>$file['size'],'type'=>$file['type']));//echo '{"imgurl":"'.$picName.'"}';}}}
?>



最后:开发难点:

1、因为xhr对象已经预置了上传过程中的各种参数,比如上传进度回调函数,所以直接利用xhr对象实现进度条
但是jquery的ajax函数不提供原始的xhr对象,而只有在open函数前设置progress进度函数才起作用,所以无法
直接实现,但是jqeury的ajax函数可以使用自己建立的xhr对象,于是在ajax函数之前创建自己的xhr函数并设置
进度显示函数:onprogress
var upload_ajax_request=$.ajax({url: 'uploadtemp.php',type: 'POST',data: formdata,cache: false,processData: false,contentType: false,//这里我们先拿到jQuery产生的 XMLHttpRequest对象,为其增加 progress 事件绑定,然后再返回交给ajax使用xhr: function(){var xhr = $.ajaxSettings.xhr();if(onprogress && xhr.upload) {xhr.upload.addEventListener("progress" , onprogress, false);return xhr;}},success:function(data,status){//alert(data);var obj;try {obj = JSON.parse(data);}catch (e){alert("error:"+data);//$this.button('上传出错');}//ShowObjProperty(obj);for(file_name in obj){//indexif(obj[file_name].success){//上传成功//上传成功从文件上传队列移除$("li[name='upload_"+file_name+"']").slideUp('slow',function(){$("li[name='upload_"+file_name+"']").remove();});createFileUploadSuccessView(obj[file_name],$("#download_file_list"));//从队列里面删除返回成功的filevar index=$.inArray(file_name,file_list.file_name_list);if(index!=-1){file_list.file_name_list.splice(index,1);file_list.splice(index,1);}$("li[name='upload_"+file_name+"'] div[name='msg']").html("<a href='"+obj[file_name].url+"'><font color='green'>上传成功</font></a>").fadeIn();}else{//上传失败$("li[name='upload_"+file_name+"'] div[name='msg']").html("<font color='color'>"+obj[file_name].msg+"</font>").fadeIn();$("li[name='upload_"+file_name+"'] button").removeClass("disabled").text("移除");}}if(file_list.length==0){$("#file_list_progress").slideUp();$("#start_upload_file_list").slideUp();}$("#abort_upload_file_list").fadeOut();$this.button('reset');//alert(status);},error:function(xhr,error,exception){alert(error);},complete:function(XHR, TS){},beforeSend:function(xhr){}});

2、通过每次file input对象的每次change事件,记录选择的文件,将其记录到file_list数组,并将file对象的value值置null,不然每次选择同样的文件会不响应change函数
 $("#fileupload2").change(function(){
some scripts;//必须先把处理代码卸了//解决下次选择同样数据不响应,直接将本次数据清空$("#fileupload2").val('');
}



3、在上传按钮的点击事件中,再将file_list文件队列安置到formData对象,然后利用ajax向后台发送文件
var formdata=new FormData();for(index in file_list){if(!isEmptyObject(file_list[index])){file_num=file_num+1;file_total_size=file_total_size+file_list[index].size;formdata.append(file_list_name,file_list[index]);}}



更多推荐

手动实现完全加强版js文件上传到php

本文发布于:2024-03-09 20:22:15,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1726028.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:加强版   文件上传   js   php

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!