推荐的分块大小是2M-5M,具体size根据产品中文件上传的大小分布来定。若是上传的文件大部分是500M以上,很大的文件,建议是5M, 若是相对较小,推荐2M。javascript
节省流量,避免上传重复的分块。php
减小用户等待时间。css
可恢复的上传。出现中断,就算浏览器刷新或者是换了台电脑也能恢复到上次中断的位置。html
如下代码上传音频有点问题,上传进度没有作,往后闲时补上。html5
(function ($, global, doc) { var form = doc.forms["upload"]; // Upload类 function Upload (file) { this.file = file; this.fileInfo = { fileName: this.file.name, fileType: this.file.type, fileSize: this.file.size }; this.reader = new FileReader(); // 开始读取指定的Blob对象或File对象中的内容. 当读取操做完成时,readyState属性的值会成为DONE,若是设置了onloadend事件处理程序,则调用之.同时,result属性中将包含所读取文件的原始二进制数据. this.reader.readAsBinaryString(this.file); // 块大小默认为4MB this.opts = { chunkSize: 4 * 1024 * 1024, chunkIndex: 0 }; $.extend(this.opts, { chunkCount: Math.ceil(this.fileInfo.fileSize / this.opts.chunkSize) }); this.bindEvent(); return this; }; Upload.prototype = { bindEvent: function () { var self = this; self.reader.onloadstart = function () { self.uploadChunk(); }; return self; }, uploadFinish: function (data) { var self = this; var previewStr = ''; switch (self.fileInfo.fileType.substring(0, self.fileInfo.fileType.indexOf('/'))) { case 'image': previewStr = '<img src="' + ('upload/' + data.url) + '">'; $('.preview').html(previewStr); break; case 'audio': previewStr = '<audio src="' + ('upload/' + data.url) + '" controls="controls"></audio>'; break; default: $('.preview').html(previewStr); } return self; }, updateProcess: function () { return this; }, uploadChunkAfter: function (data) { var self = this; self.opts.chunkIndex++; if (self.opts.chunkIndex < self.opts.chunkCount) { self.uploadChunk(); } else { self.uploadFinish(data); } updateProcess(); return self; }, uploadChunk: function () { var fData = new FormData(); var self = this; fData.append("file", self.file.slice(self.opts.chunkIndex * self.opts.chunkSize, self.opts.chunkSize * (self.opts.chunkIndex + 1))); fData.append("fileName", self.fileInfo.fileName); fData.append("fileSize", self.fileInfo.fileSize); fData.append("fileType", self.fileInfo.fileType); fData.append("chunkCount", self.opts.chunkCount); fData.append("chunkIndex", self.opts.chunkIndex); fData.append("trueName", self.fileInfo.fileName.substring(0, self.fileInfo.fileName.lastIndexOf('.'))); $.ajax({ url: 'controller/upload.php', type: 'POST', data: fData, processData: false, contentType: false, cache: false, dataType: "json", success: function (data) { self.uploadChunkAfter(data); } }); return self; }, util: function () { return { // 字节转换成对应的单位 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; } } } }; $('#submit').on('click', function () { var File = new Upload(form["file"].files[0]); return false; }); })(jQuery, window, document);
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <title>分块上传</title> </head> <body> <form name="upload" action="" enctype="multipart/form-data" method="post"> <input type="file" id="file" name="file"> <input type="button" id="submit" value="提交"> </form> <div class="preview"></div> <script src="http://cdn.bootcss.com/jquery/2.1.4/jquery.min.js"></script> <script src="js/upload.js"></script> </body> </html>
<?php $fsize = $_POST['fileSize']; $findex =$_POST['chunkIndex']; $ftotal =$_POST['chunkCount']; $ftype = $_POST['fileType']; $fdata = $_FILES['file']; $fname = mb_convert_encoding($_POST['fileName'],"gbk","utf-8"); $truename = mb_convert_encoding($_POST['trueName'],"gbk","utf-8"); $path = "../"; $dir = $path."upload/".$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); } ?>
fexjava