Showing posts with label Upload. Show all posts
Showing posts with label Upload. Show all posts

HTML5 WebSocket File Tranfer

Websockets Introduction

Websockets API establish a persistent connection between the client and the server. It provides bi-directional communication, client and server can communicate each other directly, It helps to avoids long polling. Webscokets enables communication between any domain. Several implementations available to use websockets in different languages.

Implementing file transfer using websockets is complex part, but transfer rate is really high compared to HTTP file transfer. Websocket file transfer gives more features like pause, resume, transfer stats, etc..



Uploading files using websockets

  1. Assign unique id to each file. 
  2. Slice file into chucks as per chuck size using File Slice.
  3. Read the chunk using File Reader.
  4. Send the each chunk as buffered object using websocket.
  5. After receive of chunk acknowledgement from server, send the next chunk.
  6. At the end of file, send complete message to notify server.
  7. Server side, on start of each file create file with unique id in temporary folder.
  8. On receive of each chuck from client add it to the corresponding file.
  9.  Send acknowledgement to client on each update.
  10. After receive of complete message rename and move it to specified folder.

Uploading large files using websockets

Large file uploading may hang the application, to avoid application hang run file reading and slicing in thread. Threading in javascript can implement using webworkers, So move slicing and reading of file to webworker.



HTML5: Recording Audio,Video Streams

HTML5: Recording Audio,Video Streams

MediaStreamRecorder API is webRTC API that supports recording streams with getUserMedia or remote streams passed over peerconnection session.



 
    <script language="javascript" type="text/javascript">
    function onVideoFail(e) {
        console.log('webcam fail!', e);
      };
 
    function hasGetUserMedia() {
      // Note: Opera is unprefixed.
      return !!(navigator.getUserMedia || navigator.webkitGetUserMedia ||
                navigator.mozGetUserMedia || navigator.msGetUserMedia);
    }
 
    if (hasGetUserMedia()) {
      // Good to go!
    } else {
      alert('getUserMedia() is not supported in your browser');
    }
 
    window.URL = window.URL || window.webkitURL;
    navigator.getUserMedia  = navigator.getUserMedia ||
                             navigator.webkitGetUserMedia ||
                              navigator.mozGetUserMedia ||
                               navigator.msGetUserMedia;
 
    var video = document.querySelector('video');
    var streamRecorder;
    var webcamstream;
 
    if (navigator.getUserMedia) {
      navigator.getUserMedia({audio: true, video: true}, function(stream) {
        video.src = window.URL.createObjectURL(stream);
        webcamstream = stream;
    //  streamrecorder = webcamstream.record();
      }, onVideoFail);
    } else {
        alert ('failed');
    }
 
    function startRecording() {
        streamRecorder = webcamstream.record();
        setTimeout(stopRecording, 10000);
    }
    function stopRecording() {
        streamRecorder.getRecordedData(postVideoToServer);
    }
    function postVideoToServer(videoblob) {
 
        var data = {};
        data.video = videoblob;
        data.metadata = 'test metadata';
        data.action = "upload_video";
        jQuery.post("uploadvideo.php", data, onUploadSuccess);
    }
    function onUploadSuccess() {
        alert ('video uploaded');
    }
 
    </script>
 



    <video autoplay></video>
    <div id="webcamcontrols">
        <button class="recordbutton" onclick="startRecording();">RECORD</button>
    </div>


"getRecorderdedData" return  blob that was recorded.


HTML5 Video Streaming: Media Source API

Streaming Video using HTML5 is now very simple, Media Source API gives streaming video as chunks. playing video with chunks of data is now possible.


This API allows to generate media streams, using  javascript streaming is enabled by extending HMTLElement.

<video id="video" src="" height="300" width="300">
      Video element is not supported in your browser
</video>




window.MediaSource = window.MediaSource || window.WebKitMediaSource;

var mediasource = new MediaSource();

var video = document.getElementById('video');
video.src = window.URL.createObjectURL(ms);

mediasource.addEventListener('webkitsourceopen', function(e) {
  ...
  var sourceBuffer = mediasource.addSourceBuffer('video/webm; codecs="vorbis,vp8"');
  sourceBuffer.append(oneVideoWebMChunk);
  ...
//start playing after video header recieved(i.e; first chunk)
//call media.endOfStream(); before appending last chunk
}, false);

playing large volume media files is a bit hard, just make them as chunks and stream with video element. Remember that Video file header contains vital information to play video, this should be necessary to seek and play stream video. if you want to play video from a segment you should first load video fie header then load the segment data to stream your data.

you start playing the stream after receiving header only.

Media Source API now works only chrome( set --enable-media-source flag ).
Media Source Extensions specification changed, changes expected to be made in next release.

Mastering in HTML5 Webworkers



One of the intresting useful feature of HTML5 is webworkers. Webworkers are helpful to create responsive and high computational applications. It solves many issues regarding performance of apps and high computations with less resources, we can easily migrate to webworkers to get more performance by implementing apps with webworkers. The blocking of UI and getting the kill pages and Aw,snap massages will no longer exists.


workers

webworker specification api allows the authors to run the scripts in background indepandantly without affecting user interface scripts. webworkers runs like thread. computing in webworkers will give high performance to app.

webworker support checking

Major user agents IE10.0,FF3.5+,chrome 4.0+,Safari6.0+,Opera10.6+ supports webworkers. Programatically checking webworker support.
if(window.Worker)
{
 console.log('webworker support');
}  
else{
 console.log('Oops! no webworker supprt');
}
 

Types of webworkers

We have two kinds of workers. They are
Dedicated workers: it has global access, same for all the documents.
Shared workers: it has ports access, changes with the connection.
*This part covers dedicated workers and the shared workers are covered in next part.


Defining worker

We can define the workers in two ways
external workers
Inline workers/embended workers


External workers

Defining workers needs a url to communicate with the script through transferable objects. This example just demonstrate worker initialization.
var worker= new Worker('worker_script.js'); 
// This defines worker script path to connect

Communication with worker

when postMessage() is called worker handles the data with onmessage() event and it will perform the operations on recieved data. The below code is to send message to worker.
worker.postMessage("Hi this is raju"); 
//this is to send message
  

Handling messages in workers

When message recieved from main page the onmessage event handles data. This example is to handling messages in workers

***** worker_script.js *****

onmessage=function(e){
 //Handle the messages with event
 var data=e.data;
 //this is the data recieved from UI
}

Sending messages from workers

postmessage() is to sending the messages to UI. This code to send message from worker.
onmessage-function(e){
 var data=e.data;
 //recieved data
 postMessage('This is recieved message'+e.data); 
 //sending message to UI
}

Handling worker Messages

worker messages are handle in UI using worker onmessage event. The code just handle messages of workers.
worker.onmessage=function(e){
 var worker_data=e.data; 
 // recieved data from worker
 alert(worker_data);
}

Handling Errors in workers:

worker returns the error lineno, filename, message. The code displays lineno, filename and message.
worker.onerror=function(e){
console.log( 'ERROR: Line '+ e.lineno+ ' in '+ e.filename+ ': '+ e.message);
}
   

Finally a simple example of using worker. This Example exibhits how sending messsage to worker and message from worker.


**** UI script ****

var worker= new Worker('worker_script.js'); 
// This defines worker script path to connect
worker.postMessage("Hi this is raju"); 
//this is to send message
worker.onmessage=function(e){
 var worker_data=e.data; 
 // recieved data from worker
 alert(worker_data);
}
worker.onerror=function(e){
 console.log( 'ERROR: Line '+ e.lineno+ ' in '+ e.filename+ ': '+ e.message);
}
 
  

**** worker_script.js ****

onmessage-function(e){
 var data=e.data; 
 //recieved data from UI
 postMessage('This is recieved message'+e.data); 
 //sending message to UI
}
  

Structered way of message passing to workers/JSON Data handling in workers

Suppose you need to handle the multiple computations in the workers for that you need to handle the data in stuctured format i.e; json format.
look at the example of handling multiple operations in the workers. This example demonstrates how to handle when multiple messages are sent to worker

**** main page ****

var worker=new Worker('worker_script.js');
  
worker.postmessage(JSON.stringify({'op' : 'mult', x : 4, y : 6}));
worker.postmessage(JSON.stringify({'op' : 'add', x : 6, y : 9}));
worker.postmessage('wrong data');
  
worker.onmessage=function(e){
 alert(e.data)
}
 

**** worker_script.js ****

function addNumbers(x,y) {
     return x + y;
}
 
function mulNumbers(x,y) {
   return x*y;
}
  
onmessage = function (event) {
    var data = JSON.parse(event.data);
 
    switch(data.op) {
        case 'mult':
        postMessage(mulNumbers(data.x, data.y));
        break;
        case 'add':
        postMessage(addNumbers(data.x, data.y));
        break;
        default:
        postMessage("Wrong operation specified");
    }
};

Here the code is for sending addition and multiple requests and processing computation in worker then return the result to main page.

workers/ Embended workers:

Inline workers can ba added in two ways one is by using createObjectURL and other is script tag type attribute worker/javascript. This example demonstrate how to add inline workers using blob and createObjectURl.
var bb = new BlobBuilder();
bb.append("onmessage = 
function(e) 
{ 
 postMessage('Inline worker creation'); 
}");

var blobURL = window.URL.createObjectURL(bb.getBlob());

var worker = new Worker(blobURL);
worker.onmessage = function(e) {
  alert(e.data)
};
worker.postMessage();

The above code initializes BlobBuilder and append it with worker code.
Then it create url for blob.
Finally Initializes the worker with generated URL.

Sub workers:

Deviding tasks among workers is the easy using subworkers. Here we are taking multiple operations and passing the objects to the main worker and it will divert the calls to subworkers.

**** main page ****

var worker=new Worker('worker_script.js');
  
worker.postmessage(JSON.stringify({'op' : 'mult', x : 4, y : 6}));
worker.postmessage(JSON.stringify({'op' : 'add', x : 6, y : 9}));
worker.postmessage('wrong data');

worker.onmessage=function(e){
 alert(e.data)
}

**** worker_script.js ****

  
var thisworker=this;
var add = new Worker('subworker1.js');
var mult= new Worker('subworker2.js');
  
add.onmessage=function(e){
 thisworker.postMessage(e.data);
} 

mult.onmessage=function(e){
 thisworker.postMessage(e.data);
} 

thisworker.onmessage = function (event) {
    var data = JSON.parse(event.data);
 
    switch(data.op) {
        case 'mult':
        mult.postMessage(JSON.stringify(data.x, data.y));
        break;
        case 'add':
        add.postMessage(JSON.stringify(data.x, data.y));
        break;
        default:
       thisworker.postMessage("Wrong operation specified");
    }
};

**** subworker1.js ****

onmessage=function(e) {
 var data=JSON.parse(e.data)
    var result= data.x + data.y;
    postMessage(result);
}

**** subworker2.js ****

onmessage = function(e) {
 var data = JSON.parse(e.data)
 var result = data.x * data.y;
 postMessage(result);
}

The above code simple sends the send the multiple messages to the main thread. Then the processing of cumputation done in subworkers.


Terminating the webworkers

Two ways you can terminate workers.
From app : worker.termiante();
From worker: self.close();


Workers Not have access:

The DOM
The window object
The document object
The parent object


Importing scripts in workers

importScripts('Base64.js'); //Single script
importScripts('Base64.js','FileSaver.js'); //multiple scripts importing

*DOM based scripts cannot be import
**After importing total script only worker started
**imported scripts errors should be handled



Worker specific classes

FileReaderSync to read file or blob inside worker
FileWriterSync to write file
RequestFileSystemSync for file system handling
IndexedDBSync in for client side database storage


DOM functions available in workers

atob() //Not in chrome
btoa() //Not in chrome
dump()
clearInterval()
clearTimeout()
setInterval()
setTimeout()
Navigator object
location object
Application Cache

*Some useful APIs are not supported by webworkers like websockets,localstorage,etc..


Classes available in workers

XMLHttpRequest()
Worker()


Webworkers Errors and Debugging:

Chrome developer tools has an advantage of debugging worker scripts. and you can place breakpoints, scope of variables etc... You can also use stacktrace.js

Security locks

Due to chrome security issues and same origin consideration, chrome doesn't allow local file access as worker script, for that you should start the chrome with the flag --allow-file-access-from-files or you need to run the app from your local host.


Things you should keep in mind the objects cannots be passed through webworkers if you try to do this. You will get DATA_CLONE_ERR DOM Exception 25.
Some API's are not supported in workers, if you try to pass or access unsupported API's in webworkers, you will get SECURITY_ERR DOM Exception 18.
If You want pass the objects to the workers,you should use JSON.stringify for object to string and JSON.parse or eval() for String to object.



HTML5 File Transfer using webworkers and XHR2 is demonstrated here. 

Further reading :

  1. webworker detail explanation 
  2. Using webworkers
  3. Webworker standard 
  4. Webworker specificaton 
  5. HTML5 Presentation 
 

Drag and Drop Directory/Folder Upload HTML5


HOW TO HANDLE Directory uploads

You can upload directory by using webkitdirectory or mozdirectory

<input type='file'  webkitdirectory='true'   mozdirectory='true' >

Chrome 21 allows you to drop a folder or multiple folders into the browser window. To handle these, you need to change the way how you handle dropped objects.

Drag and Drop Directory/Folder Upload HTML5


<div id=”dropzone”></div>

var dropzone = document.getElementById('dropzone');
dropzone.ondrop = function(e) {
  var length = e.dataTransfer.items.length;
  for (var i = 0; i < length; i++) {
    var entry = e.dataTransfer.items[i].webkitGetAsEntry();
    if (entry.isFile) {
      ... // do whatever you want
    } else if (entry.isDirectory) {
      ... // do whatever you want
    }
  }
};
Notice that big change in drop event . chrome introduced call webkitGetAsEntry(). It will specify whether the dropped object is file or folder. and it will return Name and Fullpath also.

entry.fullPath() will give the path of the item.

For reading the entries in the directory entry you have to use directory reader.
In case of direcory follow the steps
  1.  call createReaer callback for direntry 
  2. then store the entries in array
  3. again check for entry type
  4. In case of file call the file callback
  5. it will return filename,size and mime type
Here sample algorithm code for directory entry reading
var direntry=entry.createReader();
entries=direntry.entries(); 
entries.forEach(function(entry){
//again check for again type
}); 

Further Reading:
  1. Html5 Rocks updates 
  2. Demo of Drag and drop DIrectory upload
  3. HTML5 Presentation
 
HTML5 Websocket File manager

HTML5 Websocket File manager

This article demonstrates how to build file manager using Websockets and with other HTML5 emerging technologies.

WebSockets one of the powerful communication mechanism  to send and receive the messages bidirectionally between client and server. WebSockets give you the facility to load real time data and visualize it.

PDF.js, webodf.js and so many other libraries exists over web to load  and see the files in browser. The HTML5 Drag Drop API has the Capability to get the files from the user in a way they can drop in the zone. With  Drag and Drop user can upload Folder and multiple files.

One other HTML5 very useful API WebWorkers it helps to do the operation in their own thread. it gives boost to javascript to implement multi-threading.

And Finally there are lots of libraries to show the structure of different levels in tree view and the grid structure.

By using all these feature one can create easily a file manager with all the below features.
  1. Opening the document in the cloud
  2. Drag and Drop upload
  3. High performance File operations
  4. Large file upload(>1GB)
  5. Directory Upload
  6. Multiple file upload
  7. Tree Based Presentation
  8. Document information
and many more...

Dropbox, Google Drive and now you can have yours...

 Further Reading:
  1. Websocket Basics 
  2. Mozilla Developer Network 
  3. Websocket specification 
  4. Websocket community 
  5. HTML5