用HTML5实现断点续传、上传进度条、图片预览 【2】
用HTML5实现断点续传、上传进度条、图片预览 【2】 · Oct 10, 2014 404 clicks
在上一篇文章中,已经基本实现了文件上传的所有功能,还遗留了2个问题:一是计算文件hash时一次性读取了文件内容,存在内存限制; 二是只实现了单文件上传
事实上,Spark MD5给出了分片读取文件,计算md5值的过程。
照着那个例子,把代码重新修改了下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 | <!doctype html> < html > < head > < title >Upload File via XMLHttpRequest 2</ title > < script src = "spark_md5.min.js" ></ script > < script > var fr_supported = typeof FileReader != 'undefined'; var fd_supported = typeof FormData != 'undefined'; if ( !fr_supported ){ alert('you browser doesnt support FileReader!'); } if ( !fd_supported ){ alert('you browser doesnt support FormData!'); } function get(id){ return document.getElementById(id); } var pos = 0; var slice_size = 1024 * 1024; var upload_data=null; var upload_finished = false; var upload_file_size = 0; var upload_file = null; var upload_file_hash= ''; function fileSelected(){ var file = get('fileToUpload').files[0]; upload_file = file; pos = 0; upload_data = null ; upload_finished = false; upload_file_hash = ''; if ( file ){ upload_file_size = file.size; 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'; } get('fileName').innerHTML = file.name; get('fileSize').innerHTML = fileSize; get('fileType').innerHTML = file.type; //preview image if ( file.type.split('/')[0] == 'image' ){ var rd = new FileReader(); rd.addEventListener('load',function(evt){ var im = new Image(); im.src = evt.target.result; get('preview').innerHTML = ''; get('preview').appendChild(im); },false); rd.readAsDataURL(file); } } } function checkFileMd5(file,callback) { var blobSlice = File.prototype.slice || File.prototype.mozSlice || File.prototype.webkitSlice; var chunk_size = 1024 * 1024 *10; //10M var current_chunk = 0; var chunk_count = Math.ceil(file.size / chunk_size); var spark = new SparkMD5.ArrayBuffer(); var rd = new FileReader(); rd.addEventListener('load',function(evt){ spark.append(evt.target.result); current_chunk ++; if (current_chunk < chunk_count ){ loadNext(); }else{ callback(file, spark.end() ); } }); rd.addEventListener('error',function(evt){ console.log(['err ocurs while computing hash']); }) function loadNext(){ var start = current_chunk * chunk_size, end = ((start+chunk_size)>=file.size) ? file.size : start+chunk_size; rd.readAsArrayBuffer(blobSlice.call(file,start,end)) }; loadNext(); } function uploadFile() { var file = upload_file; //get md5 hash checkFileMd5(file,afterCheckhash); } function afterCheckhash(file,hash_val) { upload_file_hash = hash_val; //console.log(['md5', upload_file_hash ]); //get size of uploaded data var xhr = new XMLHttpRequest(); var fd = new FormData(); fd.append('act','query'); fd.append('qry_fname', file.name ); fd.append('file_hash', upload_file_hash); xhr.addEventListener('load',function(stat){ pos = parseInt(this.responseText); //console.log([upload_file,pos,upload_file_size]); if ( pos < upload_file_size ){ upload_data = upload_file .slice(pos, pos+slice_size); upload_finished = (pos + slice_size) >= upload_file_size; get('progressNumber').innerHTML = Math.round(pos*100/upload_file_size)+'%'; //upload file do_upload_file(); }else{ upload_finished = true; get('progressNumber').innerHTML = '100%'; alert('file already upladed'); } },false); xhr.open("POST",'upload.php'); xhr.send(fd); } function do_upload_file(){ if ( upload_data==null ){ alert( 'nothing to upload' ); return; } var xhr = new XMLHttpRequest(); var fd = new FormData(); fd.append('act','upload'); fd.append('uploadfile', upload_data ); fd.append('filename', upload_file.name); fd.append('finished', upload_finished?'1':'0' ); fd.append('position', pos); fd.append('file_hash', upload_file_hash); xhr.upload.addEventListener("progress", uploadProgress,false); xhr.addEventListener("load", uploadComplete,false); xhr.addEventListener("error", uploadFailed,false); xhr.addEventListener("abort", uploadCanceled, false); xhr.open("POST", "upload.php"); xhr.send(fd); } function uploadProgress(evt){ var percent = 'unable to compute progress'; if (evt.lengthComputable){ var percent = Math.round( (evt.loaded+pos)*100/upload_file_size ) + '%'; } get('progressNumber').innerHTML = percent; } function uploadComplete(evt){ //alert( evt.target.responseText ); //console.log([evt.target.responseText]); if ( !upload_finished ){ pos += slice_size; upload_data = upload_file.slice(pos, pos+slice_size); upload_finished = (pos + slice_size) >= upload_file_size; do_upload_file(); } } function uploadFailed(evt){ alert('Failed to upload'); } function uploadCanceled(evt){ alert('the upload has been canceled'); } </ script > < body > < form action = "upload.php" id = "form1" method = "post" enctype = "multipart/form-data" > < div class = "row" > < label for = "fileToUpload" >Select a File to Upload</ label > < br /> < input type = "file" name = "fileToUpload" id = "fileToUpload" onchange = "fileSelected()" /> </ div > < p >FileName: < span id = "fileName" ></ span ></ p > < p >FileSize: < span id = "fileSize" ></ span ></ p > < p >FileType: < span id = "fileType" ></ span ></ p > < p id = "preview" ></ p > < div class = "row" > < input type = "button" onclick = "uploadFile()" value = "Upload" /> </ div > < p >Progress: < span id = "progressNumber" ></ span ></ p > </ form > |