Skip to content

Instantly share code, notes, and snippets.

@georapbox
Forked from alediaferia/tiny_uploader.js
Last active June 13, 2019 12:23
Show Gist options
  • Save georapbox/95a98b6d0435f2de29b00f68abf1ad1c to your computer and use it in GitHub Desktop.
Save georapbox/95a98b6d0435f2de29b00f68abf1ad1c to your computer and use it in GitHub Desktop.
A tiny snippet for reading files chunk by chunk in plain JavaScript
/**
* Read files chunk by chunk.
*
* @param {File} file The file object to read in chunks.
* @param {Object} [options={}] Options object to override defaults.
* @param {Number} [chunkSize= 64 * 1024] The chunk size (in bytes) to be used. Default is 64KB.
* @param {Boolean} [binary=false] If true chunks will be read through FileReader.readAsArrayBuffer otherwise as FileReader.readAsText. Default is `false`.
* @param {Function} [chunkReadCallback=()=>{}] Optional function that accepts the read chunk as its only argument.
* If `binary` option is set to `true`, this function will receive an instance of `ArrayBuffer`, otherwise a `String`.
* @param {Function} [chunkErrorCallback=()=>{}] Optional function that accepts an object of type `FileReader.error`.
* @param {Function} [successCallback=()=>{}] Optional function invoked as soon as the whole file has been successfully read.
* @returns {undefined}
*/
function readFileInChunks(file, options = {}) {
const defaults = {
chunkSize: 64 * 1024, // bytes
binary: false,
chunkReadCallback: () => {},
chunkErrorCallback: () => {},
successCallback: () => {}
};
options = {
...defaults,
...options
};
const { binary, chunkSize, chunkReadCallback, chunkErrorCallback, successCallback } = options;
const fileSize = file.size;
let offset = 0;
const onLoadHandler = evt => {
if (evt.target.error == null) {
offset += binary ? evt.target.result.byteLength : evt.target.result.length;
chunkReadCallback(evt.target.result);
} else {
return chunkErrorCallback(evt.target.error);
}
if (offset >= fileSize) {
return successCallback(file);
}
readBlock(offset, chunkSize, file);
};
const readBlock = (_offset, length, _file) => {
const reader = new FileReader();
const blob = _file.slice(_offset, length + _offset);
reader.onload = onLoadHandler;
if (binary) {
reader.readAsArrayBuffer(blob);
} else {
reader.readAsText(blob);
}
};
readBlock(offset, chunkSize, file);
}
export default readFileInChunks;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment