Async file streaming from JS to PHP using WebWorkers
This gist demonstrate how to read a file from the browser using javascript asynchronously with web workers, and how to process the file on PHP server side.
Angular2 Client Side
For demo and source code check src/app.ts in Pluker Preview
HTML
Angular2 Template
<input type='file' (change)="openFile($event)">
A simple input field, that triggers openFile function when on change event fires.
Typescript
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
openFile(e) {
if (e.target.files[0]) {
let file = e.target.files[0];
// Build a worker from an anonymous function body
var blobURL = URL.createObjectURL(
new Blob([
'(',
function () {
self.addEventListener(
'message',
function (e) {
try {
postMessage({
result: new FileReaderSync().readAsArrayBuffer(e.data)
});
} catch (e) {
postMessage({result: 'error'});
}
},
false
);
}.toString(),
')()' ]
, {type: 'application/javascript'}
)
);
let worker = new Worker(blobURL);
worker.onmessage = (e) => {
let fileData = new Int8Array(e.data.result);
// fileData contains the streamed file
this.ngZone.run(() => {
this.stream = fileData.join(",");
});
};
worker.postMessage(file);
}
}
- WebWorkers need to be defined as a seperate JS file, instead we use a Blob to inline the worker from an anonymous function.
- Since webworkers run on their own thread, we have to call
ngZone.run
to update Angular2 view fromsyncWorker.onmessage
callback.
Typings
If your IDE or Webpack complains about missing typings for the webworkers or FileReaderSync functions, add custom typings to your angular2 bootstraping file.
main.bowser.d.ts
interface FileReaderSync {
readAsArrayBuffer(blob: Blob): any;
readAsBinaryString(blob: Blob): void;
readAsDataURL(blob: Blob): string;
readAsText(blob: Blob, encoding?: string): string;
}
declare var FileReaderSync: {
prototype: FileReaderSync;
new(): FileReaderSync;
};
declare function postMessage(data: any): void;
main.browser.ts
// <reference path="./main.browser.d.ts" />
PHP Server Side
Streamed file can be sent to a PHP Backend using WebSocket and processed in PHP. Here an example of how to read the Int8Array buffer view in PHP as an array of lines (useful for CSV parsing).
$text = implode(array_map('chr', $file));
$lines = array_filter(explode(PHP_EOL, $text));