JS可断点续传文件上传实现代码解析_javascript技巧

来源:脚本之家  责任编辑:小易  

www.zgxue.com防采集请勿采集本网。

刚开始学习前端开发就碰到文件上传问题,还要求可断点续传。查了很多资料,发现H5的file API刚好可以满足我们的需求,也遇到了一些问题,于是记录下来为有同样需求的朋友提供一些帮助。

一、首先,为了引入文件对象,需要在H5页面上放置一个file类型的输入标签。

<input type="file" onchange="fileInfo()">

当选择文件之后显示文件相关信息:

function fileInfo() { let fileObj = document.getElementById('file').files[0]; console.log(fileObj); }

我们获取到的对象本身是一个数组,这里只选择了一个文件,需要选择多个文件可在input标签添加multiple属性。现在我们打开浏览器控制台可以看到输出了文件的最后修改时间、文件大小和文件名等信息:

二、好了,当我们获取到选择的文件对象之后,现在需要把文件上传到服务器,可以模拟表单事件进行上传,需要引入FormData对象,其次,由于HTTP对文件上传大小的限制,所以要对文件切块上传,在服务器收到文件块之后拼接成一个整体,最后还需要一个进度条去显示上传进度。在理清了思路以后这就动手实现:

先在H5页面放置一个进度条,同时将选择文件改变的事件更换为上传文件块的函数upload(开始上传字节处),这里我们从第0个字节开始上传,也就是从头开始传:

 <input type="file" id="file" onchange="upload(0)">

 <progress id="progress" max="100" value="0"></progress>

然后来实现文件块的上传函数:

// 文件切块大小为1MBconst chunkSize = 1024 * 1024;// 从start字节处开始上传function upload(start) { let fileObj = document.getElementById('file').files[0]; // 上传完成 if (start >= fileObj.size) { return; } // 获取文件块的终止字节 let end = (start + chunkSize > fileObj.size) ? fileObj.size : (start + chunkSize); // 将文件切块上传 let fd = new FormData(); fd.append('file', fileObj.slice(start, end)); // POST表单数据 let xhr = new XMLHttpRequest(); xhr.open('post', 'upload.php', true); xhr.onload = function() { if (this.readyState == 4 && this.status == 200) { // 上传一块完成后修改进度条信息,然后上传下一块 let progress = document.getElementById('progress'); progress.max = fileObj.size; progress.value = end; upload(end); } } xhr.send(fd);}

这里使用原生的JS向服务器发送请求,将文件切块使用函数slice(开始位置,结束位置),然后将文件块封装到FormData对象实现模拟表单的文件上传。后台我使用PHP接收数据,也可以使用其他后端语言:

<?php // 追加文件块 $fileName = $_FILES['file']['name']; file_put_contents('files/' . $fileName, file_get_contents($_FILES['file']['tmp_name']), FILE_APPEND);?>

在这里我新建了一个文件夹files,将上传的文件存放到这里。获取的文件块内容采用追加的形式FILE_APPEND。于是我们打开浏览器上传文件:

然后查看一下files文件夹下面是否接收到vscode.exe文件:

三、有了文件上传功能,接下来我们要实现断点续传功能。在上一步文件切块的基础上,断点续传变得非常简单,如果突然断网或者浏览器意外关闭,那么上传的是不完整的文件,我们只需要在选择了文件以后向服务器查询一下服务器上相同文件名的大小,然后将开始上传位置(字节)设置到这个大小即可:

先定义一个初始化函数当选择文件后向服务器查询已上传文件大小:

// 初始化上传大小function init() { let fileObj = document.getElementById('file').files[0]; let xhr = new XMLHttpRequest(); xhr.onreadystatechange = function() { if (this.readyState == 4 && this.status == 200) { // 将字符串转化为整数 let start = parseInt(this.responseText); // 设置进度条 let progress = document.getElementById('progress'); progress.max = fileObj.size; progress.value = start; // 开始上传 upload(start); } } xhr.open('post', 'fileSize.php', true); // 向服务器发送文件名查询大小 xhr.send(fileObj.name);}

在服务器端使用fileSize.php查询已上传文件大小:

<?php // 接收文件名 $fileName = file_get_contents('php://input'); $fileSize = 0; $path = 'files/' . $fileName; //查询已上传文件大小 if (file_exists($path)) { $fileSize = filesize($path); } echo $fileSize;?>

最后将H5页面上input标签的onchange事件改为init():

<input type="file" onchange="init()">

同时upload函数也不需要重复设置进度条的最大值,修改为:

 // 上传一块完成后修改进度条信息,然后上传下一块

 document.getElementById('progress').value = end;

 upload(end);

然后打开浏览器,在上传过程中故意关闭浏览器下次再选择同一文件时即可从断点位置开始续传。

四、虽然已经实现了可断点续传的文件上传功能,但是界面还需要美化一下,这里引用bootstrap框架,需要jquery,顺便用jquery的ajax代替原生JS的ajax,需要注意的是$.ajax的processData和contentType属性都要设置成false:

// POST表单数据$.ajax({ url: 'upload.php', type: 'post', data: fd, processData: false, contentType: false, success: function() { upload(end); }});

最后美化完成的效果图如下:

没有办法,实践证明最好的解决办法是自己写一个OCX控件,这样就只要注册一下OCX控件就可以了,同时OCX控件的可扩展性非常大,也就是给vc\delphi这些程序的功能引入到web中,其功能可想而知! 这里不说明OCX开发的过程了,给自己写的OCX控件共享一下,希望能给一些朋友提供帮助。 这个OCX控件中提供了一个getFiles()方法,只要获取控件对象,然后调用getFiles()方法就可以获取对应路径下的所有文件,如下图: 该控件可以选择任意盘符下的任意文件夹,图中最下面的按钮时web中的input,通过web中的js方法来获取文件列表,OCX 的getFiles()方法返回文件名串,样式如1.jpg;2.jpg;3.jpg,每个文件名中间用“;”链接,在js中使用split方法来分离一下就可以了。 页面代码如下: 复制代码 代码如下:<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>无标题文档</title> <script type="text/javascript"><!-- function show(){ var obj=document.getElementById("pathOcx"); var str=obj.getFiles(); var list=str.split(";"); for(var i=0;i<list.length;i++){ if(list[i]!=""){ alert(list[i]);     } } } // --></script> </head> <body> <OBJECT id="pathOcx"      classid="clsid:13BF0862-063C-432F-A8DF-07C2823E8562"      width=420      height=300      align=center      hspace=0      vspace=0 > </OBJECT> <br> <input type="button" name="Submit" value="显示数据" onClick="show()"> </body> </html> 这样就可以使用该控件选取任意文件夹了,并且可以通过js获取文件夹中的所有内容,由于篇幅有限,这里不对该OCX更多的功能做说明,下篇准备给OCX增加上传功能,这样既可以上传整个文件夹,而且支持断点续传。 最后注明:OCX使用的时候需要注册控件 注册方法:运行cmd,进入比如OCX控件在C:\123.OCX,在cmd中运行RegSvr32   c:\123.OCX,会提示注册成功,然后就可以在网页中使用了!打包下载内容来自www.zgxue.com请勿采集。


  • 本文相关:
  • javascript之分片上传,断点续传的实际项目实现详解
  • js断点调试心得分享(必看篇)
  • chrome调试折腾记之js断点调试技巧
  • 基于javascript实现前端文件的断点续传
  • 前端js实现文件的断点续传 后端php文件接收
  • chrome浏览器如何断点调试异步加载的js
  • 使用chrome调试javascript的断点设置和调试技巧
  • js调试系列 断点与动态调试[基础篇]
  • bootstrap tooltip插件源码解析
  • 如何用javascript实现功能齐全的单链表详解
  • javascript实现随机点名器
  • js返回顶部实例代码
  • js字符限制(字符截取) 一个中文汉字算两个字符
  • echarts学习笔记之图表自适应问题详解
  • 一步一步的了解webpack4的splitchunk插件(小结)
  • js前端日历控件(悬浮、拖拽、自由变形)
  • js与运算符和或运算符的妙用
  • 滚动条代码生成器
  • javascript 选择文件夹对话框(web)
  • 网站首页网页制作脚本下载服务器操作系统网站运营平面设计媒体动画电脑基础硬件教程网络安全基础知识javascript类库表单特效广告代码网页特效黑客性质javascript技巧domnode.jsjs其它首页javascriptjavascript之分片上传,断点续传的实际项目实现详解js断点调试心得分享(必看篇)chrome调试折腾记之js断点调试技巧基于javascript实现前端文件的断点续传前端js实现文件的断点续传 后端php文件接收chrome浏览器如何断点调试异步加载的js使用chrome调试javascript的断点设置和调试技巧js调试系列 断点与动态调试[基础篇]bootstrap tooltip插件源码解析如何用javascript实现功能齐全的单链表详解javascript实现随机点名器js返回顶部实例代码echarts学习笔记之图表自适应问题详解一步一步的了解webpack4的splitchunk插件(小结)js前端日历控件(悬浮、拖拽、自由变形)js与运算符和或运算符的妙用滚动条代码生成器js刷新页面方法大全js中settimeout()的用法详解js截取字符串常用方法详细整理js页面跳转常用的几种方式js打开新窗口的2种方式js数组与字符串的相互转换方法js删除数组里的某个元素方法js设置cookie、读取cookie、删除js 将json字符串转换为json对象的javascript深入理解js闭包捕获浏览器关闭、刷新事件不同情况下的处详解javascript utc时间转换方法微信小程序canvas绘制圆角base64图片的实javascript监听页面刷新和页面关闭事件方前端性能优化及技巧本窗口将在秒后自动关闭javascript给按钮绑定点击事件(onclick)基于jquery的图片不完全按比例自动缩小详解webpack2+react 实例demobootstrap中glyphicons-halflings-regula
    免责声明 - 关于我们 - 联系我们 - 广告联系 - 友情链接 - 帮助中心 - 频道导航
    Copyright © 2017 www.zgxue.com All Rights Reserved