一直以来我都特别好奇,网上很多文件断点上传是怎么实现的,像百度云,最近看到一篇关于HTML5新特性的文章,里面的BLOB对象和FILE对象,有一个slice方法,可以将BLOB对象进行分割。BLOB(Binary Large Object)二进制大对象,属于XMLHttpRequest2.0中的一员,它的slice方法和字符串和数组的slice方法一样,用于分割二进制。
文件上传后台我是使用php的,上传的策略是先请求后台询问上传的文件是否存在,如果存在则发回已经上传到哪里。然后前端拿到这个位置,对文件二进制进行分割。
好,先看看我前端的实现,后台写得太烂,我就不贴出来了,php的文件主要使用两个函数,一个是file_put_contents,还有就是file_get_contents
<!DOCTYPE html> <html> <head> <title>断点续传</title> </head> <style type="text/css"> input[type="file" i] { width: 100px; height: 50px; opacity: 0; /*visibility: hidden;*/ margin: 0; padding: 0; border: 0; float: left; } .upload-button-wrap { position: relative; display: inline-block; vertical-align: middle; } .upload-button-wrap:hover .upload-button { border-color: #000; } .clearfix:after { content: ‘‘; clear: both; display: block; } .clearfix { zoom: 1; } .upload-button { width: 100px; height: 50px; position: absolute; left: 0; top: 0; z-index: -1; } .upload-wrap { position: relative; } #uploadButton { display: inline-block; } </style> <body> <div class="upload-wrap"> <div class="upload-button-wrap clearfix"> <input type="file" id="uploadFile"> <button class="upload-button">选择图片</button> </div> <button id="uploadButton">上传</button> </div> <script type="text/javascript"> (function (w) { var fileUpload = function (config) { var _files = [], // 要上传文件的队列 _file = null, // 当前上传的文件 _upload = config.uploadId, // input[type = "file"]的控件ID _submit = config.submitId, // input[type = "submit"]的控件ID _url = config.url, _unit = 1024, _start = 0, _xmlRequest = new XMLHttpRequest(); var _init = function () { document.getElementById(_upload).addEventListener("change", function (e) { _files = this.files; _file = _files[0]; e.preventDefault(); }, false); document.getElementById(_submit).addEventListener("click", function (e) { // 向后抬请求文件是否存在 _xmlRequest.onload = function () { if (_xmlRequest.readyState == 4 && _xmlRequest.status == 200) { _start = parseInt(_xmlRequest.responseText); _uploadFile(); } _xmlRequest.onload = function () { if (_xmlRequest.readyState == 4 && _xmlRequest.status == 200) { if (_xmlRequest.responseText == "success") { _start = _start + _unit; _uploadFile(); } } } }; _getSetbacks(); e.preventDefault(); }, false); }, // 获取文件进度 _getSetbacks = function () { _xmlRequest.open("GET", _url+"?fileName="+_file.name, true); _xmlRequest.send(null); }, // 上传文件 _uploadFile = function () { if (_start > _file.size) return; console.log(_start); var formData = new FormData(); formData.append(‘fileName‘, _file.name); formData.append(‘fileContent‘, _file.slice(_start,_start+_unit)); _xmlRequest.open("POST", _url, true); _xmlRequest.send(formData); }; _init() } w.fileUpload = fileUpload; })(window) var f = new fileUpload({ uploadId: ‘uploadFile‘, submitId: ‘uploadButton‘, url: ‘./upload.php‘ }) </script> </body> </html>
我先请求后台,通过_getSetback函数获取文件进度,返回的是已经上传文件的大小,然后根据文件大小对文件进行切分(slice),最后通过_uploadFile分多次上传文件。
时间: 2024-10-10 15:42:41