XMLHttpRequest上传文件实现进度条项目整理
发布时间:2018-07-18, 16:25:54 分类:HTML | 编辑 off 网址 | 辅助
正文 4826字数 795,387阅读
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>XMLHttpRequest上传文件进度实现</title>
<script type="text/javascript">
var xhr;
var ot;//
var oloaded;
//上传文件方法
function UpladFile() {
var fileObj = document.getElementById("file").files[0]; // js 获取文件对象
var url = "uploadFile"; // 接收上传文件的后台地址
var form = new FormData(); // FormData 对象
form.append("mf", fileObj); // 文件对象
xhr = new XMLHttpRequest(); // XMLHttpRequest 对象
xhr.open("post", url, true); //post方式,url为服务器请求地址,true 该参数规定请求是否异步处理。
xhr.onload = uploadComplete; //请求完成
xhr.onerror = uploadFailed; //请求失败
xhr.upload.onprogress = progressFunction;//【上传进度调用方法实现】
xhr.upload.onloadstart = function(){//上传开始执行方法
ot = new Date().getTime(); //设置上传开始时间
oloaded = 0;//设置上传开始时,以上传的文件大小为0
};
xhr.send(form); //开始上传,发送form数据
}
//上传进度实现方法,上传过程中会频繁调用该方法
function progressFunction(evt) {
var progressBar = document.getElementById("progressBar");
var percentageDiv = document.getElementById("percentage");
// event.total是需要传输的总字节,event.loaded是已经传输的字节。如果event.lengthComputable不为真,则event.total等于0
if (evt.lengthComputable) {//
progressBar.max = evt.total;
progressBar.value = evt.loaded;
percentageDiv.innerHTML = Math.round(evt.loaded / evt.total * 100) + "%";
}
var time = document.getElementById("time");
var nt = new Date().getTime();//获取当前时间
var pertime = (nt-ot)/1000; //计算出上次调用该方法时到现在的时间差,单位为s
ot = new Date().getTime(); //重新赋值时间,用于下次计算
var perload = evt.loaded - oloaded; //计算该分段上传的文件大小,单位b
oloaded = evt.loaded;//重新赋值已上传文件大小,用以下次计算
//上传速度计算
var speed = perload/pertime;//单位b/s
var bspeed = speed;
var units = 'b/s';//单位名称
if(speed/1024>1){
speed = speed/1024;
units = 'k/s';
}
if(speed/1024>1){
speed = speed/1024;
units = 'M/s';
}
speed = speed.toFixed(1);
//剩余时间
var resttime = ((evt.total-evt.loaded)/bspeed).toFixed(1);
time.innerHTML = ',速度:'+speed+units+',剩余时间:'+resttime+'s';
if(bspeed==0)
time.innerHTML = '上传已取消';
}
//上传成功响应
function uploadComplete(evt) {
//服务断接收完文件返回的结果
// alert(evt.target.responseText);
alert("上传成功!");
}
//上传失败
function uploadFailed(evt) {
alert("上传失败!");
}
//取消上传
function cancleUploadFile(){
xhr.abort();
}
</script>
</head>
<body>
<progress id="progressBar" value="0" max="100" style="width: 300px;"></progress>
<span id="percentage"></span><span id="time"></span>
<br /><br />
<input type="file" id="file" name="myfile" />
<input type="button" onclick="UpladFile()" value="上传" />
<input type="button" onclick="cancleUploadFile()" value="取消" />
</body>
</html>
Run code
Cut to clipboard
若想用jQuery 中的ajax实现的话,jQuery的 ajax 方法没有关于 progress 事件的操作,此时需要调用的XMLHttpRequest对象是指定progress 事件。
$.ajax({
type: "POST",
url: "upload",
data: formData , //这里上传的数据使用了formData 对象
processData : false,
//必须false才会自动加上正确的Content-Type
contentType : false ,
//这里我们先拿到jQuery产生的 XMLHttpRequest对象,为其增加 progress 事件绑定,然后再返回交给ajax使用
xhr: function(){
var xhr = $.ajaxSettings.xhr();
if(onprogress && xhr.upload) {
xhr.upload.onprogress = progressFunction;
return xhr;
}
}
});
Run code
Cut to clipboard
XMLHttpRequest对象,传送数据的时候,有一个progress事件,用来返回进度信息。
它分成上传和下载两种情况
1)下载的progress事件属于XMLHttpRequest对象
2)上传的progress事件属于XMLHttpRequest.upload对象。
下载进度实现:
xhr.onprogress = downloadProgress;
function downloadProgress(event) {//未测试
if(event.lengthComputable) {
var percentComplete = event.loaded / event.total;
}
}
Run code
Cut to clipboard
(支付宝)给作者钱财以资鼓励 (微信)→
有过 2 条评论 »
function uptx(){ $('.up_buttom').removeAttr('onclick'); $('.up_buttom').text('正在上传....'); var formData = new FormData($('#myformup')[0]); $.ajax({ type: "POST", url:'/index.php/Members/Uptx/index', //data:$('#myformup').serialize(), cache: false, data: new FormData($('#myformup')[0]), processData: false, contentType: false, error: function(request) { alert('服务器繁忙'); location.reload(); return false; //alert("提交失败"); }, success: function(data) { if(data=='upok'){ alert('上传修改头像成功'); location.reload(); return false; }else{ alert('上传失败'); location.reload(); return false; } } }); }
success: function(data){ //data=JSON.parse(data); //alert(file); var upToken=data.upToken; var nnaame=data.nnaame; var xhr = new XMLHttpRequest(), fd = new FormData; xhr.open('POST', 'https://up.qbox.me', true); // 'url' //可以通过progress事件监听上传进度 xhr.onload = function() { // 上传完成 //alert(nnaame); $('.watermark').hide(); if(typestrsff=='video') codeanddd('contentadddd','[testmp4]https://out.img.pan.lizhenqiu.com/'+nnaame+'[/testmp4]'); else if(typestrsff=='audio') codeanddd('contentadddd','[testmp3]https://out.img.pan.lizhenqiu.com/'+nnaame+'[/testmp3]'); else if(typestrsff!='image' && nttyyynammmname) codeanddd('contentadddd','[testurl=https://out.img.pan.lizhenqiu.com/'+nnaame+'?download/'+nttyyynammmname+']'+nttyyynammmname+'[/testurl]'); else codeanddd('contentadddd','[testimg]https://out.img.pan.lizhenqiu.com/'+nnaame+'[/testimg]'); $('#myCanvasimgpuppmain').hide(); submitinputtvllsscccc("上传成功!"); $('#getimgupjinduidd').css({'height':'0px','width':'0px'}); } // xhr.upload.onprogress = function (evt) { if (evt.lengthComputable) { var percentComplete = Math.round(evt.loaded * 100 / evt.total); //document.getElementById('progressNumber').innerHTML = percentComplete.toString() + '%'; //console.log(percentComplete.toString() + '%'); $('#submitinputtvllss').text("正在上传.. "+percentComplete.toString() + '%'); $('#getimgupjinduidd').css({'height':'100%','width':+percentComplete.toString() + '%'}); } else { //console.log('无法计算'); //document.getElementById('progressNumber').innerHTML = '无法计算'; } } xhr.onerror = function (e){ /*document.getElementById("myformssssww").submit(); setTimeout(function(){ nnntimgetimg(); },2500); return false;*/ $('#submitinputtvllss').text('该浏览器不支持拖曳上传,请选择文件。'); alert('该浏览器不支持拖曳上传,请选择文件。');path.click();return false; } fd.append('file', file); // 'file' fd.append('key', nnaame); fd.append('token', upToken); xhr.send(fd); }
<!DOCTYPE html> <html> <head> <title>Upload Files using XMLHttpRequest - Minimal</title> </head> <body> <form id="form1" enctype="multipart/form-data" method="post" action="Upload.aspx"> <div class="row"> <label for="fileToUpload">Select a File to Upload</label><br> <input type="file" name="fileToUpload" id="fileToUpload" onchange="fileSelected();"> </div> <div id="fileName"></div> <div id="fileSize"></div> <div id="fileType"></div> <div class="row"> <input type="button" onclick="uploadFile()" value="Upload"> </div> <div id="progressNumber"></div> </form> <script> function fileSelected() { var file = document.getElementById('fileToUpload').files[0]; if (file) { var fileSize = 0; if (file.size > 1024 * 1024){ fileSize = (Math.round(file.size * 100 / (1024 * 1024)) / 100).toString() + 'MB'; }else{ fileSize = (Math.round(file.size * 100 / 1024) / 100).toString() + 'KB'; } document.getElementById('fileName').innerHTML = 'Name: ' + file.name; document.getElementById('fileSize').innerHTML = 'Size: ' + fileSize; document.getElementById('fileType').innerHTML = 'Type: ' + file.type; } } </script> </body> </html>
var fd = new FormData(document.getElementById('form1'));
这个构造函数的优点是可以用所有表单填充FormData实例(不必手动完成)
let arr = [1, 2, 2, 3]; let set = new Set(arr); let newArr = Array.from(set); // Array.from方法可以将 Set 结构转为数组。 console.log(newArr); // [1, 2, 3]
为什么是xmlhttp.onreadystatechange = state_Change而不是xmlhttp.onreadystatechange = state_Change();
为的是把整个函数给onreadystatechange,而不是将函数最后处理完的值返回给onreadystatechange
onreadystatechange是一个事件句柄,同样功能的还有onclick这些,就是有点击事件的时候会进行特定处理,具体看你的函数怎么写了。而onreadystatechange是由readyState触发,readyState存着XMLHttpRequest的状态,
0: 请求未初始化
1: 服务器连接已建立
2: 请求已接收
3: 请求处理中
4: 请求已完成,且响应已就绪
readyState改变,调用onreadystatechange这个函数,注意,是这个函数,那我们是不是要赋值一个函数给他,而不是单纯地返回一个值。
XMLHttpRequest 跨域时产生了 OPTIONS 请求
XMLHttpRequest上传文件实现进度条
if (window.XMLHttpRequest) { // Mozilla 浏览器 //新建XMLHttpRequest对象 xmlhttp = new XMLHttpRequest(); } else if (window.ActiveXObject) { // IE 浏览器 try { xmlhttp = new ActiveXObject("Msxml2.XMLHTTP"); } catch (e) { try { xmlhttp = new ActiveXObject("Microsoft.XMLHTTP"); } catch (e) { } } }
使用FormData向服务器发送不了数据
你真的会使用XMLHttpRequest吗?
AJAX POST&跨域 解决方案 - CORS
进度事件(Progress Events)
OPTIONS 方法在跨域请求(CORS)中的应用
解决错误指定RequestHeader导致后台接受不到FormData数据的问题
xhr文件上传,进度感知
异步上传文件,在很多场景中都有应用。本文介绍一种通过xhr和formdata实现的方法。
FormData属于h5的内容所以,浏览器兼容不是很好,下面是一种polyfill,inspired by francois2metz/html5-formdata
(function(w) { if (w.FormData) return; function FormData() { this.boundary = "--------FormData" + Math.random(); this._fields = []; } FormData.prototype.append = function(key, value) { this._fields.push([key, value]); } FormData.prototype.toString = function() { var boundary = this.boundary; var body = ""; this._fields.forEach(function(field) { body += "--" + boundary + "\r\n"; // file upload if (field[1].name) { var file = field[1]; body += "Content-Disposition: form-data; name=\""+ field[0] +"\"; filename=\""+ file.name +"\"\r\n"; body += "Content-Type: "+ file.type +"\r\n\r\n"; body += file.getAsBinary() + "\r\n"; } else { body += "Content-Disposition: form-data; name=\""+ field[0] +"\";\r\n\r\n"; body += field[1] + "\r\n"; } }); body += "--" + boundary +"--"; return body; } w.FormData = FormData; var _send = XMLHttpRequest.prototype.send; XMLHttpRequest.prototype.send = function(data) { if (data instanceof FormData) { xhr.setRequestHeader("Content-Type", "multipart/form-data;boundary="+ data.boundary); return xhr.sendAsBinary(data.toString()); } return _send.call(this, data); }; })(window);
像这样使用
var data = new FormData(); data.append('file', document.getElementById('file').files[0]); xhr.open('POST', '/', true); xhr.onprogress = (function(){ var progress = 0; return function(evt){ var p = ~~(evt.loaded*1000/evt.total) p /= 1000 if(progress !=== p){ progress = p console.log('progress: ', p) } } })();
关于兼容性,只要支持FieApi就没问题
HTML5利用FormData对象实现显示进度条的文件上传【译】
HTML5利用FormData对象实现显示进度条的文件上传【英】