html5文件上传断点续传
最近公司要做一个html5上传的jquery插件,要在下先实现功能,要求显示上传进度,文件信息,断点续传等等。我一看,艾玛!Σ(゚д゚lll),没做过啊。没办法,(# ゚Д゚),只能去查资料了。
作为一名还未毕业的大学僧,本人表示亚历山大。不过还好是做出来了,不敢说代码写得很好,大家将就着看吧。
感谢以下文章提供的思考方向:
http://www.script-tutorials.com/pure-html5-file-upload/
http://fex.baidu.com/blog/2014/04/html5-uploader/
由于传的时候不小心,文件弄错了,现在bug已修复,对不起啊大家
考虑到服务器原因现在停止上传演示页面,抱歉请大家谅解
演示地址:暂停
资源地址:我是下载地址
HTML:
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0,user-scalable=no">
<title>upload html5</title>
<link rel="stylesheet" type="text/css" href="css/style.css">
<link rel="stylesheet" type="text/css" href="css/upload.css">
</head>
<body ontouchmove="event.preventDefault()">
<div id="upload_box">
<form id="upload_form" name="upload_form" action="javascript:init();" method="post" enctype="multipart/form-data">
<div><label for="file">Please select file</label></div>
<div><input type="file" id="file" name="file" onchange="fileReady()"><div>
<input type="submit" id="submit" name="submit" value="上传">
<button id="clear" onclick="clearUploadFile()">清除</button>
<div class="upload_message_show">
<!--进度条-->
<div class="upload_bar_box">
<div class="upload_bar"></div>
<span class="upload_percent"></span>
</div>
<!--上传剩余时间和上传速度-->
<div class="upload_count">
<div class="left_time">剩余时间 | 00:00:00</div>
<div class="speed">100k/s</div>
</div>
<!--文件信息-->
<div class="upload_file_message">
<div class="message_box">
<div class="upload_file_name"></div>
<div class="upload_file_size"></div>
<div class="upload_file_type"></div>
<div class="upload_file_error"></div>
<div class="isCompleted"></div>
</div>
<!--文件预览-->
<div class="upload_file_preview"></div>
</div>
</div>
</div>
<script type="text/javascript" src="js/html5_upload_ano.js"></script>
</body>
</html>
CSS:
style.css
/*************reset****************/
html{color:#333;-webkit-text-size-adjust:none;height:100%;max-height:100%;overflow: hidden;font-family: 'Microsoft Yahei';}
body{height: 100%;max-height:100%;overflow: hidden;}
body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,code,form,fieldset,legend,input,button,textarea,p,blockquote,th,td{margin:0;padding:0;}
table{border-collapse:collapse;border-spacing:0;}
fieldset,img{border:0;}
address,caption,cite,code,dfn,em,var,optgroup{font-style:inherit;font-weight:inherit;}
del,ins{text-decoration:none;}
li{list-style:none;}
h1,h2,h3,h4,h5,h6{font-size:100%;}q:before,q:after{content:'';}
abbr,acronym{border:0;font-variant:normal;}
sup{vertical-align:baseline;}
sub{vertical-align:baseline;}legend{color:#000;}
input,button,textarea,select,optgroup,option{font-family:inherit;font-size:inherit;font-style:inherit;font-weight:inherit;}input,button,textarea,select{*font-size:100%;}
body{font-size:12px;}
a{color: #333333;text-decoration: none;}
a:hover{text-decoration:underline; color:#c00;}
/*font*/
*{
font-size: 1.05em;
color: #222;
font-family: "Microsoft Yahei";
}
upload.css
#upload_box{
padding:0em 1em;
padding-top:20px;
height:100%;
background: #74b1d1;
position: relative;
}
#upload_form{
background: #fff;
height: 80%;
padding: 1.4em 1em;
border-radius: 4px;
box-shadow: 0 1px 3px rgba(0,0,0,0.7);
}
#upload_form label{
font-size: 1.5em;
font-weight: bolder;
}
#file{
margin:20px 0;
border:1px solid #ccc;
border-radius: 5px;
padding: 0.5em;
font-size: 1.4em;
width: 90%;
}
#submit,#clear{
font-size:1.2em;
padding:0.3em 1.2em;
border-radius:10px;
border:1px solid #d9d9d9;
background: -webkit-linear-gradient(#ffffff,#dfdfdf);
background: -o-linear-gradient(#ffffff,#dfdfdf);
background: -moz-linear-gradient(#ffffff,#dfdfdf);
background: linear-gradient(#ffffff,#dfdfdf);
box-shadow:0px 1px 3px rgba(0,0,0,0.7);
outline: none;
}
#submit{
margin-right:1.6em;
}
#submit:hover,#clear:hover{
background: -webkit-linear-gradient(#66ccff,#74b1d1);
background: -o-linear-gradient(#66ccff,#74b1d1);
background: -moz-linear-gradient(#66ccff,#74b1d1);
background: linear-gradient(#66ccff,#74b1d1);
cursor: pointer;
}
.upload_message_show{
margin-top: 20px;
display: none;
}
.upload_file_message{
padding: 1.4em 0em;
padding-left: 60%;
padding-right: 1.2em;
border-radius: 10px;
background: -webkit-linear-gradient(#dfdfdf,#cccccc);
background: -o-linear-gradient(#dfdfdf,#cccccc);
background: -moz-linear-gradient(#dfdfdf,#cccccc);
background: linear-gradient(#dfdfdf,#cccccc);
font-size: 1.1em;
font-weight: bolder;
position: relative;
min-height: 6.5em;
}
.upload_file_error{
color:red;
}
.message_box{
position: absolute;
left: 1.2em;
top: 1.4em;
}
.upload_file_preview{
height: 100%;
position: relative;
}
.upload_bar_box{
width: 100%;
height: 1em;
border-radius:0.5em;
position: relative;
box-shadow:0px 0px 3px rgba(0,0,0,0.6);
line-height: 1em;
}
.upload_bar{
width:0%;
border-radius:0.5em;
background:-webkit-linear-gradient(#F01731,#F50B43);
background:-o-linear-gradient(#F01731,#F50B43);
background:-moz-linear-gradient(#F01731,#F50B43);
background:linear-gradient(#F01731,#F50B43);
height:100%;
}
.upload_percent{
position: absolute;
right: 10px;
top:0em;
font-weight:700;
}
.upload_count{
width: 100%;
font-size:0.8em;
margin-top:1em;
position: relative;
}
.left_time{
margin-left: 1em;
}
.speed{
position: absolute;
right:1em;
top: 0em;
}
js:
变量定义:
var nSlice_count = 100,//分段数,文件分段数
nFactCount, //实际分段数
nMin_size = 0.5,//最小分段大小(M)
nMax_size = 5, //最大分段大小(M)
nFactSize, //实际分段大小
nCountNum = 0, //分段标号
sFile_type, //文件类型
nFile_load_size, //文件上传部分大小
nFile_size, //文件大小
nPreuploaded = 0, //上一次记录上传部分的大小
bIs_uploading= false,//是否上传中
bStart_upload= false,//是否开始上传
bEnd_upload = false;//是否上传完成
当文件域变化或者点击清空时,重置所有已记录信息:
function messageChange(){
document.querySelector(".upload_file_name").innerHTML ="文件名称: " ;
document.querySelector(".upload_file_type").innerHTML ="文件类型: " ;
document.querySelector(".upload_file_size").innerHTML ="文件大小: " ;
document.querySelector(".isCompleted").innerHTML ="上传状态: " ;
document.querySelector(".upload_bar").style.width = "0%";
document.querySelector(".upload_percent").innerHTML = "0%";
document.querySelector(".upload_file_preview").innerHTML ="";
document.querySelector(".upload_message_show").style.display = "none";
}
function clearUploadFile(e){
var e = e || event;
e.stopPropagation();
e.preventDefault();
document.getElementById("file").value = "";
bStart_upload = false;
messageChange();
}
function fileReady(){
bIs_uploading = false;
bEnd_upload = false;
nCountNum = 0;
bStart_upload = false;
messageChange();
}
发生错误时的处理:
function errorUp(){
bStart_upload = false;
document.querySelector(".upload_file_error").innerHTML = "上传过程中出错";
}
function abortUp(){
bStart_upload = false;
document.querySelector(".upload_file_error").innerHTML = "网络故障,请检查重试";
}
文件上传后提供预览,考虑到手机小屏幕的问题,只在ipad和pc上提供预览,预览的文件类型为
image/video/audio,由于浏览器对多媒体格式的支持不同,不能保证每个文件都能正常播放
function filePreview($src){
var ftype = sFile_type;
var $temp;
var IMGMaxHeight = document.querySelector(".upload_message_show").offsetHeight;
switch(ftype){
case "image" :
$temp = '<img src="source/'+$src.url+'" style="max-height:'+IMGMaxHeight+'px;margin-left:30%;">';
break;
case "audio" :
$temp = '<audio src="source/'+$src.url+'" controls="controls"></audio>';
break;
case "video" :
$temp = '<video src="source/'+$src.url+'" controls="controls"></video>';
break;
}
var IsPreview = checkUserAgent();
if(IsPreview)
document.querySelector(".upload_file_preview").innerHTML = $temp;
}
function checkUserAgent(){
var msg = true;
var agent = ["ipod","iphone","android","symbian","windows mobile"];
var info =navigator.userAgent.toLowerCase();
for(var i=0,j=agent.length;i<j;i++)
{
if(info.indexOf(agent[i])>0)
msg = false;
}
return msg;
}
数据单位转化:
var conversion = (function(){
var unitConversion = {
bytesTosize:function(data){
var unit = ["Bytes","KB","MB","GB"];
var i = parseInt(Math.log(data)/Math.log(1024));
return (data/Math.pow(1024,i)).toFixed(1) + " " + unit[i];
},
secondsTotime:function(sec){
var h = Math.floor(sec/3600),
m = Math.floor((sec-h*3600)/60),
s = Math.floor(sec-h*3600-m*60);
if(h<10) h = "0" + h;
if(m<10) m = "0" + m;
if(s<10) s = "0" + s;
return h + ":" + m + ":" + s + ":";
}
};
return unitConversion;
})();
文件上传和上传时的计算:
//start sending
var reader = new FileReader();
var timer;
var fProgress = function(e){
var fSize = get_file_message.getAll().fileSize;
timer = setTimeout(uploadCount(e,fSize,conversion),300);
};
var floadend = function(e){
if(reader.error){alert("上传失败,出现未知错误");clearTimeout(timer);return;}
clearTimeout(timer);
if(nCountNum+1!=nFactCount)
{
if(bStart_upload)
{
nCountNum++;
uploadStart();
return;
} else {
document.querySelector(".speed").innerHTML = "0k/s";
document.querySelector(".left_time").innerHTML = "剩余时间 | 00:00:00";
return;
}
}
bEnd_upload = true;
document.querySelector(".layer_box").style.display = "none";
document.querySelector(".speed").innerHTML = "0k/s";
document.querySelector(".left_time").innerHTML = "剩余时间 | 00:00:00";
document.querySelector(".upload_percent").innerHTML = "100.00%";
document.getElementById("submit").value = "上传";
var $res = JSON.parse(e.target.responseText);
filePreview($res);
if($res.res=="success") bIs_uploading =true;
document.querySelector(".isCompleted").innerHTML="上传状态: " + (bIs_uploading?"上传完成":"正在上传..");
};
var uploadStart = function(){
var get_all = get_file_message.getAll();
var start = nCountNum * nFactSize,
end = Math.min(start+nFactSize,get_all.fileSize);
var fData = new FormData();
fData.append("file",file.slice(start,end));
fData.append("name",file.name);
fData.append("size",file.size);
fData.append("type",file.type);
fData.append("totalCount",nFactCount);
fData.append("indexCount",nCountNum);
fData.append("trueName",file.name.substring(0,file.name.lastIndexOf(".")));
document.querySelector(".layer_box").style.display = "block";
if(!sFile_type)
sFile_type = file.type.substring(0,file.type.indexOf("/"));
var xhr = new XMLHttpRequest();
xhr.upload.addEventListener("progress",fProgress,false);
xhr.addEventListener("load",floadend,false);
xhr.addEventListener("error",errorUp,false);
xhr.addEventListener("abort",abortUp,false);
xhr.open("POST","php/send/");
xhr.send(fData);
};
reader.onloadstart = function(){
var get_all = get_file_message.getAll(),
fName = get_all.fileName,
fType = get_all.fileType,
fSize = conversion.bytesTosize(get_all.fileSize);
document.querySelector(".upload_message_show").style.display = "block";
document.querySelector(".upload_file_name").innerHTML ="文件名称: " + fName;
document.querySelector(".upload_file_type").innerHTML ="文件类型: " + fType;
document.querySelector(".upload_file_size").innerHTML ="文件大小: " + fSize;
document.querySelector(".isCompleted").innerHTML ="上传状态: " + (bIs_uploading?"完成":"正在上传中..");
nFactSize = get_all.fileSize/nSlice_count;
nFactSize = (nFactSize>=nMin_size*1024*1024?nFactSize:nMin_size*1024*1024);
nFactSize = (nFactSize<=nMax_size*1024*1024?nFactSize:nMax_size*1024*1024);
nFactCount= Math.ceil(get_all.fileSize/nFactSize);
uploadStart();
};
reader.readAsBinaryString(file);
}
function uploadCount(e,fSize,conversion){
var upSize = e.loaded+nCountNum*nFactSize,
perc = (upSize*100/fSize).toFixed(2) + "%";
var speed = Math.abs(upSize - nPreuploaded);
if(speed==0){clearTimeout("timer");return;}
var leftTime = conversion.secondsTotime(Math.round((fSize-upSize)/speed));
speed = conversion.bytesTosize(speed)+"/s";
document.querySelector(".speed").innerHTML = speed;
document.querySelector(".left_time").innerHTML = "剩余时间 | " + leftTime;
document.querySelector(".upload_percent").innerHTML = perc;
document.querySelector(".upload_bar").style.width = perc;
nPreuploaded = upSize;
}
PHP:
<?php
$fsize = $_POST['size'];
$findex =$_POST['indexCount'];
$ftotal =$_POST['totalCount'];
$ftype = $_POST['type'];
$fdata = $_FILES['file'];
$fname = mb_convert_encoding($_POST['name'],"gbk","utf-8");
$truename = mb_convert_encoding($_POST['trueName'],"gbk","utf-8");
$path = "../../";
$dir = $path."source/".$truename."-".$fsize;
$save = $dir."/".$fname;
if(!is_dir($dir))
{
mkdir($dir);
chmod($dir,0777);
}
//读取临时文件内容
$temp = fopen($fdata["tmp_name"],"r+");
$filedata = fread($temp,filesize($fdata["tmp_name"]));
//将分段内容存放到新建的临时文件里面
if(file_exists($dir."/".$findex.".tmp")) unlink($dir."/".$findex.".tmp");
$tempFile = fopen($dir."/".$findex.".tmp","w+");
fwrite($tempFile,$filedata);
fclose($tempFile);
fclose($temp);
if($findex+1==$ftotal)
{
if(file_exists($save)) @unlink($save);
//循环读取临时文件并将其合并置入新文件里面
for($i=0;$i<$ftotal;$i++)
{
$readData = fopen($dir."/".$i.".tmp","r+");
$writeData = fread($readData,filesize($dir."/".$i.".tmp"));
$newFile = fopen($save,"a+");
fwrite($newFile,$writeData);
fclose($newFile);
fclose($readData);
$resu = @unlink($dir."/".$i.".tmp");
}
$res = array("res"=>"success","url"=>mb_convert_encoding($truename."-".$fsize."/".$fname,'utf-8','gbk'));
echo json_encode($res);
}
?>
还有一些细节的js这里没给出来,主要就上面的功能,有问题的话欢迎回复,楼主只是个新手,不足之处请大家多多见谅。
html5文件上传断点续传的更多相关文章
- 基于HT for Web矢量实现HTML5文件上传进度条
在HTML中,在文件上传的过程中,很多情况都是没有任何的提示,这在体验上很不好,用户都不知道到时有没有在上传.上传成功了没有,所以今天给大家介绍的内容是通过HT for Web矢量来实现HTML5文件 ...
- HTML5文件上传还有进度条
以下是自学it网--中级班上课笔记 网址:www.zixue.it 需要在chrome,ff,IE10下运行 html页面 <!DOCTYPE html> <html lang=&q ...
- Asp.net mvc 大文件上传 断点续传
Asp.net mvc 大文件上传 断点续传 进度条 概述 项目中需要一个上传200M-500M的文件大小的功能,需要断点续传.上传性能稳定.突破asp.net上传限制.一开始看到51CTO上的这 ...
- 打造 html5 文件上传组件,实现进度显示及拖拽上传,支持秒传+分片上传+断点续传,兼容IE6+及其它标准浏览器
老早就注册了博客园帐号,昨天才发现,连博客都没开,Github也是一样,深觉惭愧,赶紧潜个水压压惊`(*∩_∩*)′ 言归正传.大概许多人都会用到文件上传的功能,上传的库貌似也不少,比如(jQuery ...
- vue大文件上传断点续传解决方案
之前仿造uploadify写了一个HTML5版的文件上传插件,没看过的朋友可以点此先看一下~得到了不少朋友的好评,我自己也用在了项目中,不论是用户头像上传,还是各种媒体文件的上传,以及各种个性的业务需 ...
- chunkupload文件上传断点续传组件(java)
chunkupload简介 chunkupload是一款基于java语言的断点续传组件,针对文件上传,非文件下载,集成方便,使用简单. 从整体上讲,chunkupload会对文件进行切片处理,每个切片 ...
- chunkupload 文件上传断点续传组件(java) - 正式发布
chunkupload简介 chunkupload是一款基于java语言的断点续传组件,针对文件上传,非文件下载,集成方便,使用简单. chunkupload实现如下功能: · 实现断点续传 · ...
- AJAX文件上传实践与分析,带HTML5文件上传API。
对于HTML5已经支持AJAX文件上传了,但如果需要兼容的话还是得用一点小技巧的,HTML5等等介绍,先来看看以前我们是怎么写的. 网上可能会有一些叫AJAX文件上传插件,但在AJAX2.0之前是不可 ...
- html5文件上传
<!DOCTYPE html><html><head> <title>Html5 Ajax 上传文件</title></head> ...
随机推荐
- parquet列存储本身自带压缩 配合snappy或者lzo等可以进行二次压缩
上传txt文件到hdfs,txt文件大小是74左右. 这里提醒一下,是不是说parquet加lzo可以把数据压缩到这个地步,因为我的测试数据存在大量重复.所以下面使用parquet和lzo的压缩效果特 ...
- ansible二进制部署kubernetes集群
kubernetes版本1.21.5 需要的资源文件请自行到我的阿里云盘下载 https://www.aliyundrive.com/s/zVegF78ATDV 修改主机信息 #根据自己的主机信息自行 ...
- 前端工程化:使用 shelljs 生成 yapi 接口文件
之前的文章介绍了使用 yapi-to-typescript (下文简称 ytt)生成接口类型定义文件,方便我们直接使用接口的请求和响应类型,能减少很多写接口类型的时间. 使用 yapi-to-type ...
- JavaScript面向对象—深入ES6的class
JavaScript面向对象-深入ES6的class 前言 在前面一篇中主要介绍了JavaScript中使用构造函数+原型链实现继承,从实现的步骤来说还是比较繁琐的.在ES6中推出的class的关键字 ...
- Java学习笔记:04面向对象-内部类_访问修饰符_final
04面向对象-内部类/访问修饰符/final 1.static的介绍 static:关键字,静态的 static的作用是用来修饰类中的成员 2.访问一个类中的某一个成员变量 方法一: _1.创建对象 ...
- web自动化之selenium(二)
selenium自动化测试框架 一.什么是自动化测试 利用软件(或者说机器代替人)实现全部或者部分测试任务的过程 二.为什么要进行自动化测试 自动化测试可以完成许多手工测试无法实现或难以实现的功能 ...
- python3输出“水仙花数”
for num in range(100,1000): #如果num在[100,1000)范围,就依次循环取出num的值,第一次取100,下一次取101....最后一次取999 bai = num / ...
- kubernetes集群节点多网卡,calico指定网卡
kubernetes集群节点多网卡,calico指定网卡 1.calico如果有节点是多网卡,所以需要在配置文件中指定内网网卡 spec: containers: - env: - name: DAT ...
- Flask 之 宏
宏 对宏(macro)的理解: 把它看作 Jinja2 中的一个函数,它会返回一个模板或者 HTML 字符串 为了避免反复地编写同样的模板代码,出现代码冗余,可以把他们写成函数以进行重用 需要在多处重 ...
- CF914G Sum the Fibonacci(FWT,FST)
CF914G Sum the Fibonacci(FWT,FST) Luogu 题解时间 一堆FWT和FST缝合而来的丑陋产物. 对 $ cnt[s_{a}] $ 和 $ cnt[s_{b}] $ 求 ...