diff --git a/FileBufferReader.js b/FileBufferReader.js index 8644b0a..b8c3fc8 100644 --- a/FileBufferReader.js +++ b/FileBufferReader.js @@ -1,4 +1,4 @@ -// Last time updated: 2016-10-19 12:23:04 PM UTC +// Last time updated: 2016-11-04 7:11:11 AM UTC // ________________ // FileBufferReader @@ -229,6 +229,9 @@ } var chunkSize = options.chunkSize || 15 * 1000; + if (options.extra && options.extra.chunkSize) { + chunkSize = options.extra.chunkSize; + } var sliceId = 0; var cacheSize = chunkSize; diff --git a/FileBufferReader.min.js b/FileBufferReader.min.js index ca8cc45..9c98078 100644 --- a/FileBufferReader.min.js +++ b/FileBufferReader.min.js @@ -1,4 +1,4 @@ -// Last time updated: 2016-10-19 12:23:05 PM UTC +// Last time updated: 2016-11-04 7:11:11 AM UTC // ________________ // FileBufferReader @@ -12,4 +12,4 @@ 'use strict'; -"use strict";!function(){function FileBufferReader(){function fbrClone(from,to){if(null==from||"object"!=typeof from)return from;if(from.constructor!=Object&&from.constructor!=Array)return from;if(from.constructor==Date||from.constructor==RegExp||from.constructor==Function||from.constructor==String||from.constructor==Number||from.constructor==Boolean)return new from.constructor(from);to=to||new from.constructor;for(var name in from)to[name]="undefined"==typeof to[name]?fbrClone(from[name],null):to[name];return to}var fbr=this,fbrHelper=new FileBufferReaderHelper;fbr.chunks={},fbr.users={},fbr.readAsArrayBuffer=function(file,callback,extra){var options={file:file,earlyCallback:function(chunk){callback(fbrClone(chunk,{currentPosition:-1}))},extra:extra||{userid:0}};fbrHelper.readAsArrayBuffer(fbr,options)},fbr.getNextChunk=function(fileUUID,callback,userid){var currentPosition;"undefined"!=typeof fileUUID.currentPosition&&(currentPosition=fileUUID.currentPosition,fileUUID=fileUUID.uuid);var allFileChunks=fbr.chunks[fileUUID];if(allFileChunks){"undefined"!=typeof userid?(fbr.users[userid+""]||(fbr.users[userid+""]={fileUUID:fileUUID,userid:userid,currentPosition:-1}),"undefined"!=typeof currentPosition&&(fbr.users[userid+""].currentPosition=currentPosition),fbr.users[userid+""].currentPosition++,currentPosition=fbr.users[userid+""].currentPosition):("undefined"!=typeof currentPosition&&(fbr.chunks[fileUUID].currentPosition=currentPosition),fbr.chunks[fileUUID].currentPosition++,currentPosition=fbr.chunks[fileUUID].currentPosition);var nextChunk=allFileChunks[currentPosition];if(!nextChunk)return delete fbr.chunks[fileUUID],void fbr.convertToArrayBuffer({chunkMissing:!0,currentPosition:currentPosition,uuid:fileUUID},callback);nextChunk=fbrClone(nextChunk),"undefined"!=typeof userid&&(nextChunk.remoteUserId=userid+""),nextChunk.start&&fbr.onBegin(nextChunk),nextChunk.end&&fbr.onEnd(nextChunk),fbr.onProgress(nextChunk),fbr.convertToArrayBuffer(nextChunk,function(buffer){return nextChunk.currentPosition==nextChunk.maxChunks?void callback(buffer,!0):void callback(buffer,!1)})}};var fbReceiver=new FileBufferReceiver(fbr);fbr.addChunk=function(chunk,callback){chunk&&fbReceiver.receive(chunk,function(chunk){fbr.convertToArrayBuffer({readyForNextChunk:!0,currentPosition:chunk.currentPosition,uuid:chunk.uuid},callback)})},fbr.chunkMissing=function(chunk){delete fbReceiver.chunks[chunk.uuid],delete fbReceiver.chunksWaiters[chunk.uuid]},fbr.onBegin=function(){},fbr.onEnd=function(){},fbr.onProgress=function(){},fbr.convertToObject=FileConverter.ConvertToObject,fbr.convertToArrayBuffer=FileConverter.ConvertToArrayBuffer,fbr.setMultipleUsers=function(){}}function FileBufferReaderHelper(){function fileReaderWrapper(options,callback){function addChunks(fileName,binarySlice,addChunkCallback){numOfChunksInSlice=Math.ceil(binarySlice.byteLength/chunkSize);for(var i=0;numOfChunksInSlice>i;i++){var start=i*chunkSize;chunks[currentPosition]=binarySlice.slice(start,Math.min(start+chunkSize,binarySlice.byteLength)),callback({uuid:file.uuid,buffer:chunks[currentPosition],currentPosition:currentPosition,maxChunks:maxChunks,size:file.size,name:file.name,lastModifiedDate:file.lastModifiedDate.toString(),type:file.type}),currentPosition++}currentPosition==maxChunks&&(hasEntireFile=!0),addChunkCallback()}callback=callback||function(chunk){postMessage(chunk)};var file=options.file;file.uuid||(file.uuid=(100*Math.random()).toString().replace(/\./g,""));var chunkSize=options.chunkSize||15e3,sliceId=0,cacheSize=chunkSize,chunksPerSlice=Math.floor(Math.min(1e8,cacheSize)/chunkSize),sliceSize=chunksPerSlice*chunkSize,maxChunks=Math.ceil(file.size/chunkSize);file.maxChunks=maxChunks;var numOfChunksInSlice,hasEntireFile,currentPosition=0,chunks=[];callback({currentPosition:currentPosition,uuid:file.uuid,maxChunks:maxChunks,size:file.size,name:file.name,type:file.type,lastModifiedDate:file.lastModifiedDate.toString(),start:!0});var blob,reader=new FileReader;reader.onloadend=function(evt){evt.target.readyState==FileReader.DONE&&addChunks(file.name,evt.target.result,function(){sliceId++,(sliceId+1)*sliceSize200&&200==chunk.currentPosition&&earlyCallback&&(earlyCallback(chunk.uuid),earlyCallback=null)}var earlyCallback=options.earlyCallback;delete options.earlyCallback;fileReaderWrapper(options,processChunk)}}function FileSelector(){function selectFile(callback,multiple){var file=document.createElement("input");file.type="file",multiple&&(file.multiple=!0),file.accept=selector.accept,file.onchange=function(){return multiple?file.files.length?void callback(file.files):void console.error("No file selected."):file.files[0]?(callback(file.files[0]),void file.parentNode.removeChild(file)):void console.error("No file selected.")},file.style.display="none",(document.body||document.documentElement).appendChild(file),fireClickEvent(file)}function fireClickEvent(element){var evt=new window.MouseEvent("click",{view:window,bubbles:!0,cancelable:!0,button:0,buttons:0,mozInputSource:1});element.dispatchEvent(evt)}var selector=this;selector.selectSingleFile=selectFile,selector.selectMultipleFiles=function(callback){selectFile(callback,!0)},selector.accept="*.*"}function FileBufferReceiver(fbr){function receive(chunk,callback){if(!chunk.uuid)return void fbr.convertToObject(chunk,function(object){receive(object)});if(chunk.start&&!fbReceiver.chunks[chunk.uuid]&&(fbReceiver.chunks[chunk.uuid]={},fbr.onBegin&&fbr.onBegin(chunk)),!chunk.end&&chunk.buffer&&(fbReceiver.chunks[chunk.uuid][chunk.currentPosition]=chunk.buffer),chunk.end){var chunksObject=fbReceiver.chunks[chunk.uuid],chunksArray=[];Object.keys(chunksObject).forEach(function(item,idx){chunksArray.push(chunksObject[item])});var blob=new Blob(chunksArray,{type:chunk.type});blob=merge(blob,chunk),blob.url=URL.createObjectURL(blob),blob.uuid=chunk.uuid,blob.size||console.error("Something went wrong. Blob Size is 0."),fbr.onEnd&&fbr.onEnd(blob),delete fbReceiver.chunks[chunk.uuid],delete fbReceiver.chunksWaiters[chunk.uuid]}chunk.buffer&&fbr.onProgress&&fbr.onProgress(chunk),chunk.end||(callback(chunk),fbReceiver.chunksWaiters[chunk.uuid]=function(){function looper(){chunk.buffer&&fbReceiver.chunks[chunk.uuid]&&(chunk.currentPosition==chunk.maxChunks||fbReceiver.chunks[chunk.uuid][chunk.currentPosition]||(callback(chunk),setTimeout(looper,5e3)))}setTimeout(looper,5e3)},fbReceiver.chunksWaiters[chunk.uuid]())}var fbReceiver=this;fbReceiver.chunks={},fbReceiver.chunksWaiters={},fbReceiver.receive=receive}function merge(mergein,mergeto){if(mergein||(mergein={}),!mergeto)return mergein;for(var item in mergeto)try{mergein[item]=mergeto[item]}catch(e){}return mergein}var FileConverter={ConvertToArrayBuffer:function(object,callback){binarize.pack(object,function(dataView){callback(dataView.buffer)})},ConvertToObject:function(buffer,callback){binarize.unpack(buffer,callback)}},debug=!1,BIG_ENDIAN=!1,LITTLE_ENDIAN=!0,TYPE_LENGTH=Uint8Array.BYTES_PER_ELEMENT,LENGTH_LENGTH=Uint16Array.BYTES_PER_ELEMENT,BYTES_LENGTH=Uint32Array.BYTES_PER_ELEMENT,Types={NULL:0,UNDEFINED:1,STRING:2,NUMBER:3,BOOLEAN:4,ARRAY:5,OBJECT:6,INT8ARRAY:7,INT16ARRAY:8,INT32ARRAY:9,UINT8ARRAY:10,UINT16ARRAY:11,UINT32ARRAY:12,FLOAT32ARRAY:13,FLOAT64ARRAY:14,ARRAYBUFFER:15,BLOB:16,FILE:16,BUFFER:17};if(debug)var TypeNames=["NULL","UNDEFINED","STRING","NUMBER","BOOLEAN","ARRAY","OBJECT","INT8ARRAY","INT16ARRAY","INT32ARRAY","UINT8ARRAY","UINT16ARRAY","UINT32ARRAY","FLOAT32ARRAY","FLOAT64ARRAY","ARRAYBUFFER","BLOB","BUFFER"];var Length=[null,null,"Uint16","Float64","Uint8",null,null,"Int8","Int16","Int32","Uint8","Uint16","Uint32","Float32","Float64","Uint8","Uint8","Uint8"],binary_dump=function(view,start,length){var table=[],endianness=BIG_ENDIAN,ROW_LENGTH=40;table[0]=[];for(var i=0;ROW_LENGTH>i;i++)table[0][i]=10>i?"0"+i.toString(10):i.toString(10);for(i=0;length>i;i++){var code=view.getUint8(start+i,endianness),index=~~(i/ROW_LENGTH)+1;"undefined"==typeof table[index]&&(table[index]=[]),table[index][i%ROW_LENGTH]=16>code?"0"+code.toString(16):code.toString(16)}for(console.log("%c"+table[0].join(" "),"font-weight: bold;"),i=1;ij;j++,cursor+=unit)view.setUint16(cursor,value.charCodeAt(j),endianness);break;case Types.NUMBER:case Types.BOOLEAN:debug&&console.info("%c"+value.toString(),"font-weight:bold;"),view["set"+type_name](cursor,value,endianness),cursor+=unit;break;case Types.INT8ARRAY:case Types.INT16ARRAY:case Types.INT32ARRAY:case Types.UINT8ARRAY:case Types.UINT16ARRAY:case Types.UINT32ARRAY:case Types.FLOAT32ARRAY:case Types.FLOAT64ARRAY:var _view=new Uint8Array(view.buffer,cursor,byte_length);_view.set(new Uint8Array(value.buffer)),cursor+=byte_length;break;case Types.ARRAYBUFFER:case Types.BUFFER:var _view=new Uint8Array(view.buffer,cursor,byte_length);_view.set(new Uint8Array(value)),cursor+=byte_length;break;case Types.BLOB:case Types.ARRAY:case Types.OBJECT:break;default:throw"TypeError: Unexpected type found."}debug&&binary_dump(view,start,cursor-start)}return view},unpack=function(view,cursor){var type,length,byte_length,value,elem,i=0,endianness=BIG_ENDIAN,start=cursor;type=view.getUint8(cursor,endianness),cursor+=TYPE_LENGTH,debug&&console.info("Unpacking",type,TypeNames[type]),(type===Types.ARRAY||type===Types.OBJECT)&&(length=view.getUint16(cursor,endianness),cursor+=LENGTH_LENGTH,debug&&console.info("Content Length",length)),byte_length=view.getUint32(cursor,endianness),cursor+=BYTES_LENGTH,debug&&console.info("Byte Length",byte_length,"bytes");var type_name=Length[type],unit=null===type_name?0:window[type_name+"Array"].BYTES_PER_ELEMENT;switch(type){case Types.NULL:case Types.UNDEFINED:debug&&binary_dump(view,start,cursor-start),value=null;break;case Types.STRING:length=byte_length/unit;var string=[];for(i=0;length>i;i++){var code=view.getUint16(cursor,endianness);cursor+=unit,string.push(String.fromCharCode(code))}value=string.join(""),debug&&(console.info('Actual Content %c"'+value+'"',"font-weight:bold;"),binary_dump(view,start,cursor-start));break;case Types.NUMBER:value=view.getFloat64(cursor,endianness),cursor+=unit,debug&&(console.info('Actual Content %c"'+value.toString()+'"',"font-weight:bold;"),binary_dump(view,start,cursor-start));break;case Types.BOOLEAN:value=1===view.getUint8(cursor,endianness)?!0:!1,cursor+=unit,debug&&(console.info('Actual Content %c"'+value.toString()+'"',"font-weight:bold;"),binary_dump(view,start,cursor-start));break;case Types.INT8ARRAY:case Types.INT16ARRAY:case Types.INT32ARRAY:case Types.UINT8ARRAY:case Types.UINT16ARRAY:case Types.UINT32ARRAY:case Types.FLOAT32ARRAY:case Types.FLOAT64ARRAY:case Types.ARRAYBUFFER:elem=view.buffer.slice(cursor,cursor+byte_length),cursor+=byte_length,value=type===Types.ARRAYBUFFER?elem:new window[type_name+"Array"](elem),debug&&binary_dump(view,start,cursor-start);break;case Types.BLOB:if(debug&&binary_dump(view,start,cursor-start),window.Blob){var mime=unpack(view,cursor),buffer=unpack(view,mime.cursor);cursor=buffer.cursor,value=new Blob([buffer.value],{type:mime.value})}else elem=view.buffer.slice(cursor,cursor+byte_length),cursor+=byte_length,value=new Buffer(elem);break;case Types.ARRAY:for(debug&&binary_dump(view,start,cursor-start),value=[],i=0;length>i;i++)elem=unpack(view,cursor),cursor=elem.cursor,value.push(elem.value);break;case Types.OBJECT:for(debug&&binary_dump(view,start,cursor-start),value={},i=0;length>i;i++){var key=unpack(view,cursor),val=unpack(view,key.cursor);cursor=val.cursor,value[key.value]=val.value}break;default:throw"TypeError: Type not supported."}return{value:value,cursor:cursor}},deferredSerialize=function(array,callback){for(var length=array.length,results=[],count=0,byte_length=0,i=0;ii;i++){var start=i*chunkSize;chunks[currentPosition]=binarySlice.slice(start,Math.min(start+chunkSize,binarySlice.byteLength)),callback({uuid:file.uuid,buffer:chunks[currentPosition],currentPosition:currentPosition,maxChunks:maxChunks,size:file.size,name:file.name,lastModifiedDate:file.lastModifiedDate.toString(),type:file.type}),currentPosition++}currentPosition==maxChunks&&(hasEntireFile=!0),addChunkCallback()}callback=callback||function(chunk){postMessage(chunk)};var file=options.file;file.uuid||(file.uuid=(100*Math.random()).toString().replace(/\./g,""));var chunkSize=options.chunkSize||15e3;options.extra&&options.extra.chunkSize&&(chunkSize=options.extra.chunkSize);var sliceId=0,cacheSize=chunkSize,chunksPerSlice=Math.floor(Math.min(1e8,cacheSize)/chunkSize),sliceSize=chunksPerSlice*chunkSize,maxChunks=Math.ceil(file.size/chunkSize);file.maxChunks=maxChunks;var numOfChunksInSlice,hasEntireFile,currentPosition=0,chunks=[];callback({currentPosition:currentPosition,uuid:file.uuid,maxChunks:maxChunks,size:file.size,name:file.name,type:file.type,lastModifiedDate:file.lastModifiedDate.toString(),start:!0});var blob,reader=new FileReader;reader.onloadend=function(evt){evt.target.readyState==FileReader.DONE&&addChunks(file.name,evt.target.result,function(){sliceId++,(sliceId+1)*sliceSize200&&200==chunk.currentPosition&&earlyCallback&&(earlyCallback(chunk.uuid),earlyCallback=null)}var earlyCallback=options.earlyCallback;delete options.earlyCallback;fileReaderWrapper(options,processChunk)}}function FileSelector(){function selectFile(callback,multiple){var file=document.createElement("input");file.type="file",multiple&&(file.multiple=!0),file.accept=selector.accept,file.onchange=function(){return multiple?file.files.length?void callback(file.files):void console.error("No file selected."):file.files[0]?(callback(file.files[0]),void file.parentNode.removeChild(file)):void console.error("No file selected.")},file.style.display="none",(document.body||document.documentElement).appendChild(file),fireClickEvent(file)}function fireClickEvent(element){var evt=new window.MouseEvent("click",{view:window,bubbles:!0,cancelable:!0,button:0,buttons:0,mozInputSource:1});element.dispatchEvent(evt)}var selector=this;selector.selectSingleFile=selectFile,selector.selectMultipleFiles=function(callback){selectFile(callback,!0)},selector.accept="*.*"}function FileBufferReceiver(fbr){function receive(chunk,callback){if(!chunk.uuid)return void fbr.convertToObject(chunk,function(object){receive(object)});if(chunk.start&&!fbReceiver.chunks[chunk.uuid]&&(fbReceiver.chunks[chunk.uuid]={},fbr.onBegin&&fbr.onBegin(chunk)),!chunk.end&&chunk.buffer&&(fbReceiver.chunks[chunk.uuid][chunk.currentPosition]=chunk.buffer),chunk.end){var chunksObject=fbReceiver.chunks[chunk.uuid],chunksArray=[];Object.keys(chunksObject).forEach(function(item,idx){chunksArray.push(chunksObject[item])});var blob=new Blob(chunksArray,{type:chunk.type});blob=merge(blob,chunk),blob.url=URL.createObjectURL(blob),blob.uuid=chunk.uuid,blob.size||console.error("Something went wrong. Blob Size is 0."),fbr.onEnd&&fbr.onEnd(blob),delete fbReceiver.chunks[chunk.uuid],delete fbReceiver.chunksWaiters[chunk.uuid]}chunk.buffer&&fbr.onProgress&&fbr.onProgress(chunk),chunk.end||(callback(chunk),fbReceiver.chunksWaiters[chunk.uuid]=function(){function looper(){chunk.buffer&&fbReceiver.chunks[chunk.uuid]&&(chunk.currentPosition==chunk.maxChunks||fbReceiver.chunks[chunk.uuid][chunk.currentPosition]||(callback(chunk),setTimeout(looper,5e3)))}setTimeout(looper,5e3)},fbReceiver.chunksWaiters[chunk.uuid]())}var fbReceiver=this;fbReceiver.chunks={},fbReceiver.chunksWaiters={},fbReceiver.receive=receive}function merge(mergein,mergeto){if(mergein||(mergein={}),!mergeto)return mergein;for(var item in mergeto)try{mergein[item]=mergeto[item]}catch(e){}return mergein}var FileConverter={ConvertToArrayBuffer:function(object,callback){binarize.pack(object,function(dataView){callback(dataView.buffer)})},ConvertToObject:function(buffer,callback){binarize.unpack(buffer,callback)}},debug=!1,BIG_ENDIAN=!1,LITTLE_ENDIAN=!0,TYPE_LENGTH=Uint8Array.BYTES_PER_ELEMENT,LENGTH_LENGTH=Uint16Array.BYTES_PER_ELEMENT,BYTES_LENGTH=Uint32Array.BYTES_PER_ELEMENT,Types={NULL:0,UNDEFINED:1,STRING:2,NUMBER:3,BOOLEAN:4,ARRAY:5,OBJECT:6,INT8ARRAY:7,INT16ARRAY:8,INT32ARRAY:9,UINT8ARRAY:10,UINT16ARRAY:11,UINT32ARRAY:12,FLOAT32ARRAY:13,FLOAT64ARRAY:14,ARRAYBUFFER:15,BLOB:16,FILE:16,BUFFER:17};if(debug)var TypeNames=["NULL","UNDEFINED","STRING","NUMBER","BOOLEAN","ARRAY","OBJECT","INT8ARRAY","INT16ARRAY","INT32ARRAY","UINT8ARRAY","UINT16ARRAY","UINT32ARRAY","FLOAT32ARRAY","FLOAT64ARRAY","ARRAYBUFFER","BLOB","BUFFER"];var Length=[null,null,"Uint16","Float64","Uint8",null,null,"Int8","Int16","Int32","Uint8","Uint16","Uint32","Float32","Float64","Uint8","Uint8","Uint8"],binary_dump=function(view,start,length){var table=[],endianness=BIG_ENDIAN,ROW_LENGTH=40;table[0]=[];for(var i=0;ROW_LENGTH>i;i++)table[0][i]=10>i?"0"+i.toString(10):i.toString(10);for(i=0;length>i;i++){var code=view.getUint8(start+i,endianness),index=~~(i/ROW_LENGTH)+1;"undefined"==typeof table[index]&&(table[index]=[]),table[index][i%ROW_LENGTH]=16>code?"0"+code.toString(16):code.toString(16)}for(console.log("%c"+table[0].join(" "),"font-weight: bold;"),i=1;ij;j++,cursor+=unit)view.setUint16(cursor,value.charCodeAt(j),endianness);break;case Types.NUMBER:case Types.BOOLEAN:debug&&console.info("%c"+value.toString(),"font-weight:bold;"),view["set"+type_name](cursor,value,endianness),cursor+=unit;break;case Types.INT8ARRAY:case Types.INT16ARRAY:case Types.INT32ARRAY:case Types.UINT8ARRAY:case Types.UINT16ARRAY:case Types.UINT32ARRAY:case Types.FLOAT32ARRAY:case Types.FLOAT64ARRAY:var _view=new Uint8Array(view.buffer,cursor,byte_length);_view.set(new Uint8Array(value.buffer)),cursor+=byte_length;break;case Types.ARRAYBUFFER:case Types.BUFFER:var _view=new Uint8Array(view.buffer,cursor,byte_length);_view.set(new Uint8Array(value)),cursor+=byte_length;break;case Types.BLOB:case Types.ARRAY:case Types.OBJECT:break;default:throw"TypeError: Unexpected type found."}debug&&binary_dump(view,start,cursor-start)}return view},unpack=function(view,cursor){var type,length,byte_length,value,elem,i=0,endianness=BIG_ENDIAN,start=cursor;type=view.getUint8(cursor,endianness),cursor+=TYPE_LENGTH,debug&&console.info("Unpacking",type,TypeNames[type]),(type===Types.ARRAY||type===Types.OBJECT)&&(length=view.getUint16(cursor,endianness),cursor+=LENGTH_LENGTH,debug&&console.info("Content Length",length)),byte_length=view.getUint32(cursor,endianness),cursor+=BYTES_LENGTH,debug&&console.info("Byte Length",byte_length,"bytes");var type_name=Length[type],unit=null===type_name?0:window[type_name+"Array"].BYTES_PER_ELEMENT;switch(type){case Types.NULL:case Types.UNDEFINED:debug&&binary_dump(view,start,cursor-start),value=null;break;case Types.STRING:length=byte_length/unit;var string=[];for(i=0;length>i;i++){var code=view.getUint16(cursor,endianness);cursor+=unit,string.push(String.fromCharCode(code))}value=string.join(""),debug&&(console.info('Actual Content %c"'+value+'"',"font-weight:bold;"),binary_dump(view,start,cursor-start));break;case Types.NUMBER:value=view.getFloat64(cursor,endianness),cursor+=unit,debug&&(console.info('Actual Content %c"'+value.toString()+'"',"font-weight:bold;"),binary_dump(view,start,cursor-start));break;case Types.BOOLEAN:value=1===view.getUint8(cursor,endianness)?!0:!1,cursor+=unit,debug&&(console.info('Actual Content %c"'+value.toString()+'"',"font-weight:bold;"),binary_dump(view,start,cursor-start));break;case Types.INT8ARRAY:case Types.INT16ARRAY:case Types.INT32ARRAY:case Types.UINT8ARRAY:case Types.UINT16ARRAY:case Types.UINT32ARRAY:case Types.FLOAT32ARRAY:case Types.FLOAT64ARRAY:case Types.ARRAYBUFFER:elem=view.buffer.slice(cursor,cursor+byte_length),cursor+=byte_length,value=type===Types.ARRAYBUFFER?elem:new window[type_name+"Array"](elem),debug&&binary_dump(view,start,cursor-start);break;case Types.BLOB:if(debug&&binary_dump(view,start,cursor-start),window.Blob){var mime=unpack(view,cursor),buffer=unpack(view,mime.cursor);cursor=buffer.cursor,value=new Blob([buffer.value],{type:mime.value})}else elem=view.buffer.slice(cursor,cursor+byte_length),cursor+=byte_length,value=new Buffer(elem);break;case Types.ARRAY:for(debug&&binary_dump(view,start,cursor-start),value=[],i=0;length>i;i++)elem=unpack(view,cursor),cursor=elem.cursor,value.push(elem.value);break;case Types.OBJECT:for(debug&&binary_dump(view,start,cursor-start),value={},i=0;length>i;i++){var key=unpack(view,cursor),val=unpack(view,key.cursor);cursor=val.cursor,value[key.value]=val.value}break;default:throw"TypeError: Type not supported."}return{value:value,cursor:cursor}},deferredSerialize=function(array,callback){for(var length=array.length,results=[],count=0,byte_length=0,i=0;i 2) { + document.getElementById('share-this-link').innerHTML = 'Share this link with other users!'; + info.innerHTML = 'Your UNIQUE room-id is: ' + location.hash.replace('#', '') + '. Open same URL on a new window or tab.'; + info.style.display = 'block'; + } }; websocket.push = websocket.send; websocket.send = function(data) { @@ -75,8 +83,7 @@ window.addEventListener('load', function() { var FileHelper = { onBegin: function(file) { var li = document.createElement('li'); - li.title = file.name; - li.innerHTML = '
' + file.name + '

25%
'; + li.innerHTML = '
' + file.name + '

25%
'; li.style['min-height'] = '350px'; outputPanel.insertBefore(li, outputPanel.firstChild); progressHelper[file.uuid] = { @@ -95,12 +102,19 @@ window.addEventListener('load', function() { } resetTimeCalculator(); + timeCalculator(progressHelper[file.uuid].progress); + + progressHelper.lastFileUUID = file.uuid; }, onEnd: function(file) { previewFile(file); - btnSelectFile.innerHTML = 'Select & Share A File'; - btnSelectFile.disabled = false; + btnSelectFile.innerHTML = 'Select or Drop a File'; + if (peerConnection.isOpened) { + btnSelectFile.disabled = false; + } + + progressHelper.lastFileUUID = null; }, onProgress: function(chunk) { var helper = progressHelper[chunk.uuid]; @@ -114,17 +128,36 @@ window.addEventListener('load', function() { if (chunk.currentPosition + 2 != chunk.maxChunks && helper.li.querySelector('.file-name')) { progressHelper[chunk.uuid].lastChunk = chunk; - timeCalculator(helper.progress, function(timeRemaining) { + progressHelper.callback = function(timeRemaining) { var lastChunk = progressHelper[chunk.uuid].lastChunk; - var html = (fileSelector.lastSelectedFile ? 'Sending' : 'Receiving') + ' file <' + lastChunk.name + '>:'; - html += '
Remaining chunks: ' + (lastChunk.maxChunks - lastChunk.currentPosition); - html += '
Remaining time: ' + timeRemaining; + var singleChunkSize = chunk.size / lastChunk.maxChunks; + + var html = 'File name: ' + lastChunk.name + ' (File size: ' + bytesToSize(chunk.size) + ')'; + html += '
Pieces (total/remaining): ' + lastChunk.maxChunks + '/' + lastChunk.currentPosition; + html += ' (Single piece size: ' + bytesToSize(singleChunkSize) + ')'; + + var endedAt = (new Date).getTime(); + var timeElapsed = endedAt - (progressHelper.startedAt || (new Date).getTime()); + + progressHelper.latencies.push(timeElapsed); + var avg = calculateAverage(progressHelper.latencies); + + html += '
Latency in millseconds: ' + timeElapsed + ' (Average): ' + avg + ''; + + var remainingFileSize = singleChunkSize * (lastChunk.maxChunks - lastChunk.currentPosition); + html += '
Remaining (time): ' + timeRemaining + ' (Remaining file size): ' + bytesToSize(remainingFileSize); + helper.li.querySelector('.file-name').innerHTML = html; - }); + + progressHelper.startedAt = (new Date).getTime(); + }; } else { - btnSelectFile.innerHTML = 'Select & Share A File'; - btnSelectFile.disabled = false; + btnSelectFile.innerHTML = 'Select or Drop a File'; + + if (peerConnection.isOpened) { + btnSelectFile.disabled = false; + } } } }; @@ -134,7 +167,7 @@ window.addEventListener('load', function() { var peerConnection = new PeerConnection(websocket); peerConnection.onuserfound = function(userid) { - setupOffer.innerHTML = 'Please wait a few seconds.'; + setupOffer.innerHTML = 'Detecting other users...'; setupOffer.disabled = true; peerConnection.sendParticipationRequest(userid); @@ -148,16 +181,26 @@ window.addEventListener('load', function() { setupOffer.disabled = true; btnSelectFile.disabled = false; + btnSelectFile.innerHTML = 'Select or Drop a File'; }; peerConnection.onclose = function() { onCloseOrOnError('PeerConnection is closed.'); resetButtons(); + + peerConnection.isOpened = false; + + var helper = progressHelper[progressHelper.lastFileUUID]; + if (helper && helper.li && helper.li.parentNode) { + isStoppedTimer = true; + helper.li.parentNode.removeChild(helper.li); + } }; function resetButtons() { - btnSelectFile.innerHTML = 'Select & Share A File'; + btnSelectFile.innerHTML = 'Select or Drop a File'; btnSelectFile.disabled = true; + setupOffer.disabled = false; setupOffer.innerHTML = 'Setup WebRTC Connection'; } @@ -209,20 +252,30 @@ window.addEventListener('load', function() { }; var progressIterations = 0; - var calculateInProgress = false; var ONE_SECOND = 1000; function resetTimeCalculator() { progressIterations = 0; - calculateInProgress = false; + isStoppedTimer = false; + progressHelper.callback = function() {}; + progressHelper.latencies = []; } - // https://github.com/23/resumable.js/issues/168#issuecomment-65297110 - function timeCalculator(progress, callback, selfInvoker) { - if (calculateInProgress && !selfInvoker) { - return; + function calculateAverage(arr) { + var sum = 0; + for (var i = 0; i < arr.length; i++) { + sum += parseInt(arr[i], 10); //don't forget to add the base } - calculateInProgress = true; + + var avg = sum / arr.length; + return avg.toFixed(1); + } + + var isStoppedTimer = false; + + // https://github.com/23/resumable.js/issues/168#issuecomment-65297110 + function timeCalculator(progress, selfInvoker) { + if (isStoppedTimer) return; var step = 1; @@ -241,11 +294,24 @@ window.addEventListener('load', function() { estimatedSeconds = estimatedCompletionTime % 60; displaySeconds = estimatedSeconds > 9 ? estimatedSeconds : '0' + estimatedSeconds; } - callback(displayHours + ':' + displayMinutes + ':' + displaySeconds); + + var output = ''; + if (displayHours > 0) { + output += displayHours + ' hours '; + } + if (displayMinutes > 0) { + output += displayMinutes + ' minutes '; + } + if (displaySeconds > 0) { + output += displaySeconds + ' seconds '; + } + if (output.length) { + progressHelper.callback(output); + } } setTimeout(function() { - timeCalculator(progress, callback, true); + timeCalculator(progress, true); }, step * ONE_SECOND); } @@ -260,43 +326,121 @@ window.addEventListener('load', function() { var fileBufferReader = new FileBufferReader(); + fileBufferReader.chunkSize = 60 * 1000; // 60k + fileBufferReader.onBegin = FileHelper.onBegin; fileBufferReader.onProgress = FileHelper.onProgress; fileBufferReader.onEnd = FileHelper.onEnd; - var btnSelectFile = document.getElementById('select-file'); - btnSelectFile.onclick = function() { - btnSelectFile.disabled = true; - fileSelector.selectSingleFile(function(file) { - fileSelector.lastSelectedFile = file; + function onFileSelected(file) { + fileSelector.lastSelectedFile = file; - btnSelectFile.innerHTML = 'Please wait..';; - btnSelectFile.disabled = true; + btnSelectFile.innerHTML = 'Please wait..';; + btnSelectFile.disabled = true; - fileBufferReader.readAsArrayBuffer(file, function(metadata) { - fileBufferReader.getNextChunk(metadata, getNextChunkCallback); - }); + fileBufferReader.readAsArrayBuffer(file, function(metadata) { + fileBufferReader.getNextChunk(metadata, getNextChunkCallback); + }, { + chunkSize: fileBufferReader.chunkSize }); setTimeout(function() { if (fileSelector.lastSelectedFile) return; - btnSelectFile.innerHTML = 'Select & Share A File'; + btnSelectFile.innerHTML = 'Select or Drop a File'; btnSelectFile.disabled = false; }, 5000); + } + + var btnSelectFile = document.getElementById('select-file'); + btnSelectFile.onclick = function() { + btnSelectFile.disabled = true; + fileSelector.selectSingleFile(function(file) { + onFileSelected(file); + }); }; + // drag-drop support + function onDragOver() { + mainContainer.style.border = '7px solid #98a90f'; + mainContainer.style.background = '#ffff13'; + mainContainer.style.borderRadisu = '16px'; + } + + function onDragLeave() { + mainContainer.style.border = '1px solid rgb(189, 189, 189)'; + mainContainer.style.background = 'transparent'; + mainContainer.style.borderRadisu = 0; + } + + var mainContainer = document.getElementById('main-container'); + document.addEventListener('dragenter', function(e) { + e.preventDefault(); + e.stopPropagation(); + + if (!peerConnection || !peerConnection.isOpened) return; + + e.dataTransfer.dropEffect = 'copy'; + onDragOver(); + }, false); + + document.addEventListener('dragleave', function(e) { + e.preventDefault(); + e.stopPropagation(); + + if (!peerConnection || !peerConnection.isOpened) return; + + e.dataTransfer.dropEffect = 'copy'; + onDragLeave(); + }, false); + + document.addEventListener('dragover', function(e) { + e.preventDefault(); + e.stopPropagation(); + + if (!peerConnection || !peerConnection.isOpened) return; + + e.dataTransfer.dropEffect = 'copy'; + onDragOver(); + }, false); + + document.addEventListener('drop', function(e) { + e.preventDefault(); + e.stopPropagation(); + + if (!peerConnection || !peerConnection.isOpened) return; + + onDragLeave(); + + if (!e.dataTransfer.files || !e.dataTransfer.files.length) { + return; + } + + var file = e.dataTransfer.files[0]; + + if (!peerConnection || !peerConnection.isOpened) { + alert('Pleas setup WebRTC connection before sharing this file.'); + return; + } + + onFileSelected(file); + }, false); + // -------------------------------------------------------- - setupOffer.onclick = function() { - setupOffer.innerHTML = 'Please wait a few seconds.'; - setupOffer.disabled = true; + setupOffer.onclick = function(event) { + if (event !== true) { + peerConnection.startBroadcasting(); + } - // start broadcasting userid - peerConnection.startBroadcasting(); + setupOffer.innerHTML = 'Detecting other users in this room...'; + setupOffer.disabled = true; setTimeout(function() { if (!peerConnection.isOpened) { - var innerHTML = 'Open Same URL in a NEW Tab'; + var innerHTML = 'I am alone in this room.'; setupOffer.innerHTML = innerHTML; + setTimeout(function() { + setupOffer.onclick(true); + }, 2000); } }, 5 * 1000); }; @@ -316,6 +460,21 @@ window.addEventListener('load', function() { document.getElementById('select-file').disabled = true; } + function millsecondsToSeconds(millis) { + var seconds = ((millis % 60000) / 1000).toFixed(1); + return seconds; + } + + function bytesToSize(bytes) { + var k = 1000; + var sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB']; + if (bytes === 0) { + return '0 Bytes'; + } + var i = parseInt(Math.floor(Math.log(bytes) / Math.log(k)), 10); + return (bytes / Math.pow(k, i)).toPrecision(3) + ' ' + sizes[i]; + } + function getToken() { if (window.crypto && window.crypto.getRandomValues && navigator.userAgent.indexOf('Safari') === -1) { var a = window.crypto.getRandomValues(new Uint32Array(3)), @@ -328,12 +487,4 @@ window.addEventListener('load', function() { return (Math.random() * new Date().getTime()).toString(36).replace(/\./g, ''); } } - - var uniqueToken = document.getElementById('unique-token'); - if (uniqueToken) - if (location.hash.length > 2) - uniqueToken.parentNode.parentNode.innerHTML = '

Share this Link!

'; - else - uniqueToken.innerHTML = uniqueToken.parentNode.href = '#' + getToken(); - }, false); diff --git a/dev/FileBufferReaderHelper.js b/dev/FileBufferReaderHelper.js index 49211f1..d245073 100644 --- a/dev/FileBufferReaderHelper.js +++ b/dev/FileBufferReaderHelper.js @@ -67,6 +67,9 @@ function FileBufferReaderHelper() { } var chunkSize = options.chunkSize || 15 * 1000; + if (options.extra && options.extra.chunkSize) { + chunkSize = options.extra.chunkSize; + } var sliceId = 0; var cacheSize = chunkSize; diff --git a/index.html b/index.html index 5c300e5..a7878ad 100644 --- a/index.html +++ b/index.html @@ -110,7 +110,6 @@ border:0; padding: 0; outline: none; - min-height: 350px; } video { @@ -133,6 +132,12 @@ text-align: center; display: inline-block; } + + pre { + border: 0; + margin-left: 0; + font-size: 14px; + } - - - + + + - + @@ -174,14 +179,17 @@

Watch a YouTube video to understand how it works. -
-

Demo (Open 2-similar tabs)

+
+

FileBufferReader Demo


+ +
+

@@ -189,13 +197,7 @@

Demo (Open 2-similar tabs)
    -
    - Want to share files privately? → - - - # - -
    +

    diff --git a/package.json b/package.json index 2c161e2..636d7b8 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "fbr", "preferGlobal": true, - "version": "2.0.3", + "version": "2.0.4", "author": { "name": "Muaz Khan", "email": "muazkh@gmail.com",