I have a csv file that contains bulks of data. The goal is to import this data into the database. Initially the file is processed in the client side and then when it has been validated on the client side, it is sent to the server for database inserting.
On my server-side, I use cakephp 3 framework.
What I need is to give an update (i.e. percentage of inserted data) from the controller action to the client side.
I've done research and I've stumbled across Server Sent Events which could be used for the solution. If I get the the following code to work, I can figure out how to notify the client side of the progress. However when I tryout the sample code, I keep getting the 'error' event with readyState equal to EventSource.CONNECTING.
This is the sample code taken from a tutorial site for SSE, I just tried to apply it to cakephp 3:
index.ctp
<button id="btnStartTheClock">start</button>
<button id="btnStopTheClock">stop</button>
<div id="result"></div>
<script type="text/javascript">
var essSupport = false, es, result;
function init() {
esSupport = (window.EventSource !== undefined);
result = document.getElementById("result");
document.getElementById("btnStartTheClock").onclick = startTheClock;
document.getElementById("btnStopTheClock").onclick = stopTheClock;
}
window.onload = init;
function startTheClock() {
if(esSupport) {
if (es === undefined) {
es = new EventSource("import-progress");
es.addEventListener('message', function (event) {
result.innerHTML += event.data + '<br/>';
});
es.addEventListener('open', function (e) {
result.innerHTML += "<span style='color:green;'>SSE open</span><br/>";
});
es.addEventListener('error', function(e) {
e = e || event, msg = '';
switch( e.target.readyState ){
// if reconnecting
case EventSource.CONNECTING:
msg = 'Reconnecting…';
break;
// if error was fatal
case EventSource.CLOSED:
msg = 'Connection failed. Will not retry.';
break;
}
result.innerHTML += '<span style="color:red;">' + msg + "</span><br>";
});
}
}
else {
result.innerHTML = "Your browser doesn't support server-sent events.";
}
}
function stopTheClock() {
if(esSupport) {
es.close();
result.innerHTML += "Clock Stopped.<br>";
}
}
</script>
SamplesController.php
<?php
namespace App\Controller;
use Cake\Controller\Controller;
use Cake\Controller\Component\RequestHandlerComponent;
use Cake\Event\Event;
class SamplesController extends AppController
{
public function initialize()
{
parent::initialize();
// $this->loadComponent('RequestHandler');
}
public function index()
{
}
public function importProgress()
{
$this->set('datetime', date("h:i:s"));
}
}
import_progress.ctp
<?php
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
header('Connection: keep-alive');
echo "data: The server time is: {$datetime}\n\n";
flush();
?>
If you please:
- What do I need to look for or to understand in order to achieve this goal?
- Can you suggest a different solution from this?
Side note:
- I'm new to CakePHP
- I'm new to Server Side Events
Thanks!