ajax文件上传
iframe模拟Ajax文件上传效果
分析:
1:捕捉表单提交的动作
2:创建一个iframe
3:把表单的 target修改 指向 该iframe
4:去掉这个iframe
<div id="progress"></div>
<form action="up.php" method="post" enctype="multipart/form-data" onsubmit="return ajaxup();">
<input type="file" name="pic">
<input type="submit" value="提交">
</form>
<script>
function ajaxup() {
var ifname = 'up' + Math.random();
$('<iframe name="' + ifname + '" width="0" height="0" frameBorder="0"></iframe>').appendTo($('body'));
$('form:first').attr('target', ifname);
$('#progress').html('<img src="./loading.gif" />');
}
</script>复制代码
sleep(3);
if(empty($_FILES)) {
exit('no file');
}
$msg = $_FILES['pic']['error']==0 ? 'succ' : 'fail';
echo "<script>parent.document.getElementById('progress').innerHTML = '$msg'</script>";
复制代码
formData发送数据
formData "表单数据"对象,这是在html5中新增的一个Api。 他能以表单对象做参数,自动的把表单的数据打包. 当ajax发送数据时,发送些formData,达到发送表单内各数据项的目的。
// 02-testpost.php
print_r($_POST);复制代码
<form id="tform">
用户名:<input type="text" name="username"><br>
年 龄:<input type="text" name="age"><br>
email:<input type="text" name="email"><br>
性 别:<input type="text" name="gender"><br>
<input type="button" value="ajax发送" onclick="send();">
</form>
<div id="debug"></div>
<script type="text/javascript">
function send() {
var fm = document.getElementById('tform');
var fd = new FormData(fm);
var xhr = new XMLHttpRequest();
xhr.open('POST', '02-testpost.php', true);
xhr.onreadystatechange = function () {
if (this.readyState == 4) {
document.getElementById('debug').innerHTML = this.responseText;
}
}
xhr.send(fd);
// 看下面这个例子,说明formData对象既可以从表单生成数据,也可以手动的append
var fd2 = new FormData();
fd2.append('username', 'zhangsanm');
fd2.append('age', 23);
xhr.send(fd2);
}
</script>复制代码
把二进制对象转换成浏览器显示的资源
<input type="file" name="pic" onchange="selfile();">
<div id="debug"></div>
<script type="text/javascript">
function selfile() {
var pic = document.getElementsByTagName('input')[0].files[0];
console.log(pic);
var debug = document.getElementById('debug');
var content = '';
content += '文件名称:' + pic.name + '<br />';
content += '文件大小' + pic.size + '<br />';
debug.innerHTML = content;
var tmpimg = document.createElement('img');
tmpimg.style.width = '300px';
tmpimg.src = window.URL.createObjectURL(pic); // 把二进制对象直接读成浏览器显示的资源
document.getElementsByTagName('body')[0].appendChild(tmpimg);
}
</script>复制代码
pic变量打印值,如下图所示:
通过form表单把图片发送到服务器
<input type="file" name="pic" onchange="selfile();">
<div id="debug"></div>
<script type="text/javascript">
function selfile() {
var fd = new FormData();
var pic = document.getElementsByTagName('input')[0].files[0];
// 把文件内容追加到表单数据里
fd.append('pic', pic);
var xhr = new XMLHttpRequest();
xhr.open('POST', '04-upfile.php', true);
xhr.onreadystatechange = function () {
if (this.readyState == 4) {
document.getElementById('debug').innerHTML = this.responseText;
}
}
xhr.send(fd);
}
</script>复制代码
把图片移动到上传目录
if(empty($_FILES)) {
exit('no file');
}
if($_FILES['pic']['error'] != 0) {
exit('fail');
}
move_uploaded_file($_FILES['pic']['tmp_name'],'upload/'.$_FILES['pic']['name']);
echo 'ok';复制代码
上传显示进度条
进度条需要2个最基础的信息--- 总大小,已上传大小
解决: 在html5,有一个"上传过程"的事件--onprogress事件中可以读到这2个信息
具体思路: 在上传过程中,不断的触发函数,函数读取已上传/总大小,更新页面的进度条。
<style type="text/css">
#progress {
width: 500px;
height: 30px;
border: 1px solid green;
}
#bar {
width: 0%;
height: 100%;
background: green;
}
</style>
<div id="progress"><div id="bar"></div></div>
<input type="file" onchange="selfile();">
<script type="text/javascript">
function selfile() {
var fd = new FormData();
var video = document.getElementsByTagName('input')[0].files[0];
fd.append('video', video);
var xhr = new XMLHttpRequest();
xhr.open('POST', 'upload.php', true);
// 利用XHR2的新标准,为上传过程,写一个监听函数
xhr.upload.onprogress = function (ev) {
console.log(ev);
if (ev.lengthComputable) {
var percent = 100 * ev.loaded / ev.total;
document.getElementById('bar').style.width = percent + '%';
document.getElementById('bar').innerHTML = parseInt(percent) + '%';
}
}
xhr.send(fd);
}
</script>复制代码
// upload.php
header('Access-Control-Allow-Origin: *');
// 如果接收不到文件
// 请确定 post_max_size upload_max_filesize 的大小(php.ini中)
$upfile = $_FILES['video'];
function upload_file($files, $path = "./upload", $imagesExt = ['jpg', 'png', 'jpeg', 'gif','avi', 'mp4','wmv'])
{
// 判断错误号
if (@$files['error'] == 00) {
// 判断文件类型
$ext = strtolower(pathinfo(@$files['name'], PATHINFO_EXTENSION));
if (!in_array($ext, $imagesExt)) {
return "非法文件类型";
}
// 判断是否存在上传到的目录
if (!is_dir($path)) {
mkdir($path, 0777, true);
}
// 生成唯一的文件名
$fileName = md5(uniqid(microtime(true), true)) . '.' . $ext;
// 将文件名拼接到指定的目录下
$destName = $path . "/" . $fileName;
// 进行文件移动
if (!move_uploaded_file($files['tmp_name'], $destName)) {
return "文件上传失败!";
}
return "文件上传成功!";
} else {
// 根据错误号返回提示信息
switch (@$files['error']) {
case 1:
echo "上传的文件超过了 php.ini 中 upload_max_filesize 选项限制的值";
break;
case 2:
echo "上传文件的大小超过了 HTML 表单中 MAX_FILE_SIZE 选项指定的值";
break;
case 3:
echo "文件只有部分被上传";
break;
case 4:
echo "没有文件被上传";
break;
case 6:
case 7:
echo "系统错误";
break;
}
}
}
echo upload_file($upfile);复制代码
HTML5大文件切割上传
File 继承自 Blob,Blob有slice方法,可以截取二进制对象的一部分。
思路:
1.截取10M,上传
2.判断文件有没有上传完毕。没有,继续重复步骤1、2
<style type="text/css">
#progress {
width: 500px;
height: 30px;
border: 1px solid green;
}
#bar {
width: 0%;
height: 100%;
background: green;
}
</style>
<div id="progress">
<div id="bar"></div>
</div>
<input type="file" name="mov" onchange="fire();">
<script type="text/javascript">
var xhr = new XMLHttpRequest(),clock = null;
function fire() {
clock = window.setInterval(sendfile,1000);
}
// 闭包计数器
var sendfile = (function() {
const LENGTH = 10 * 1024 * 1024; //每次切10M
var sta = 0;
var end = sta + LENGTH;
var sending = false; // 标志正在上传中
var blob = null;
var fd = null;
// 百分比
var percent = 0;
return (function () {
if(sending == true) {
return;
}
var mov = document.getElementsByName('mov')[0].files[0];
// 如果sta>mov.size,就结束了
if(sta > mov.size) {
clearInterval(clock);
return;
}
blob = mov.slice(sta,end);
fd = new FormData();
fd.append('part',blob);
up(fd);
sta = end;
end = sta + LENGTH;
sending = false; // 上传完了
percent = 100 * end / mov.size;
if(percent > 100) {
percent = 100;
}
document.getElementById('bar').style.width = percent + '%';
});
})();
function up(fd) {
xhr.open('POST','06-sliceup.php',false);
xhr.send(fd);
}
</script>复制代码
// 06-sliceup.php
// 接收文件并合并
if(!file_exists('./upload/hhr.mov')) {
move_uploaded_file($_FILES['part']['tmp_name'],'./upload/hhr.mov');
} else {
file_put_contents('./upload/hhr.mov',file_get_contents($_FILES['part']['tmp_name']),FILE_APPEND);
}
echo 'ok';复制代码
本文为作者原创文章,转载无需和我联系,但请注明转载链接。 【前端黑猫】