jQuery+php图片上传实践

最近做一个项目用到图片上传,用的是blueimp大神的jQuery-File-Upload插件,用完瞬间想研究一下图片上传原理,而且发现一个问题:多图上传时会多次发送请求~

一、图片上传原理

XMLHttpRequest Level 2 添加了一个新的接口 FormData,利用 FormData 对象,我们可以通过 JavaScript 用一些键值对来模拟一系列表单控件,我们还可以使用 XMLHttpRequest 的 send() 方法来异步的提交表单。与普通的 Ajax 相比,使用 FormData 的最大优点就是我们可以异步上传二进制文件。

FormData实例代码:

//ajax+FormData上传
function uploadByAjax(element){
    var formData = new FormData(),//创建formData对象
        fileArr = element.files, //读取文件域的文件
        fileIptName = element.name; //获取name名
    //循环将文件域的文件存入formData
    if(fileIptName && fileArr.length){
        for(var i = 0; i < fileArr.length; i++){
            formData.append(fileIptName,fileArr[i]);
        }
    }
    $.ajax({
        url: settings.url,
        type: "post",
        data: formData,
        dataType: 'json',
        cache: false,
        contentType: false,  //必须false才会自动加上正确的Content-Type
        processData: false  //必须false才会避开jQuery对 formdata 的默认处理
    }).done(function(data){
        settings.uploadSuccess(element,data);
    }).fail(function(){
        settings.uploadFail(data);
    })
}

具体的FormData用法可以访问MDN关于FormData的用法

哇,好像看起来很美好,But!!! 这是HTML5新属性而且IE10以下版本是不兼容的。

别担心!有其他的解决方案,那就是利用iframe提交。

ifame提交原理:动态创建ifame元素和form元素,插入到DOM中,把上传的input插入到form内,form的target指向iframe的name,form的action则是上传地址,上传完时刷新的是iframe,父页不会刷新,所以感觉像是无刷新上传。上传完毕后,后端会将把返回数据输出到ifame页面中,前端再读取iframe中的内容即可。

ifame实例代码:

//iframe模拟上传
function uploadByIframe(element){
    var iframe = '<iframe src="javascript:false;" name="my_upload_form_target" style="display:none;width:0;height:0;"></iframe>';
        form = '<form action="'+defaults.url+'" method="post" enctype="multipart/form-data" target="my_upload_form_target" style="display:none;width:0;height:0;"></form>',
        $iframe = $(iframe).appendTo(document.body),
        $form = $(form).appendTo(document.body),
        $file = $(element).appendTo($form);
    $form.on('submit',function(){
        $iframe.on('load',function(){
            var data = $iframe.contents().find('body').text();
            var json = eval('json='+data);
            settings.uploadSuccess(element,json);
            $iframe.remove();
            $form.remove();
        });
    });
    //触发表单提交事件
    $form.trigger('submit');
}

二、后端实现

<?php
	/*
		* [fileFileUpload 图片上传]
		* @data: 2016-12-09
		* @author: yuuk
	*/
	class upload {
		public function upload(){
			//如果有上传文件
			if($_FILES || $_POST){
				// 上传的路径,建议写物理路径
				$uploadDir = 'upload';
				// 文件数组
				$totalFile = array('status'=>1,'files'=>array());

				//formData上传
				if($_FILES['pic']){
					$fileCount = count($_FILES['pic']['name']);
				}
				//post上传
				else{
					$fileCount = count($_POST['pic']['name']);
				}

				//判断文件是否存在
				if($fileCount){
					for ($i = 0; $i < $fileCount; $i++) {
						//formData上传
						if($_FILES['pic']){
							$tempFiles = $_FILES['pic']['tmp_name'][$i]; //临时文件
							$files = $_FILES['pic']['name'][$i]; //真实文件
						}
						//post上传
						else{
							$tempFiles = $_POST['pic']['tmp_name'][$i]; //临时文件
							$files = $_POST['pic']['name'][$i]; //真实文件
						}						
						// 如果不存在文件夹则创建文件夹  
						if(!file_exists($uploadDir)){        
						    mkdir($uploadDir, 0777);    
						}    
						// 用时间戳来保存图片,防止重复
						$targetFile = $uploadDir . '/' . time() . '_' . $files;    
						// 将临时文件 移动到我们指定的路径
						move_uploaded_file($tempFiles, $targetFile);
						// 将文件地址返放入数组		
						array_push($totalFile['files'],$targetFile);
					}
				}

			    return json_encode($totalFile);;
			    exit;
		    }
		    else{
		    	die('Unable to connect');
		    	exit;
		    }
		}
	}
	$uploader = new upload();
	echo $uploader->upload();
?>

三、完整实例

移步至github项目地址:jQuery-ajaxFileUpload

打赏支持

如果文章对你有帮助就打个赏吧~

[微信] 扫描二维码打赏

[支付宝] 扫描二维码打赏

评论

还没有任何评论,你来说两句吧

发表评论

Powered By Yuuk