文章首发于qdgithub.com阅读体验更佳
分析:
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();
$(' ifname + '" width="0" height="0" frameBorder="0">').appendTo($('body'));
$('form:first').attr('target', ifname);
$('#progress').html('');
}
script>
sleep(3);
if(empty($_FILES)) {
exit('no file');
}
$msg = $_FILES['pic']['error']==0 ? 'succ' : 'fail';
echo "";
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 + '
';
content += '文件大小' + pic.size + '
';
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变量打印值,如下图所示:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-F9PqWeKZ-1576402860323)(/Uploads/2019-12-12/5df25ea50294e.png)]
<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);
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';