Skip to content

Instantly share code, notes, and snippets.

@jagomf
Last active September 29, 2018 17:34
Show Gist options
  • Save jagomf/d7c90ebe206618228818ab9211750bc7 to your computer and use it in GitHub Desktop.
Save jagomf/d7c90ebe206618228818ab9211750bc7 to your computer and use it in GitHub Desktop.
Retrieve a file and convert to base64 upon clicking on something
/**
* Prompts to choose a file from filesystem, converts to base64 (in background), and returns base64 when conversion ends.
* @param {number} maxFileSize Maximum size of file.
* @param {boolean} multiple Indicates whether to accept one or more files.
* @param {string} contentType MIME type of media to require from filesystem (can be 'image/*', etc).
* @param {string} source (For mobile devices only) If set to 'camera', tells device to capture image from camera.
* @returns {Promise} A Promise that resolves when files are read; rejects with error text if files are heavier than allowed.
*/
onClickSendMedia(maxFileSize, multiple = false, contentType = '*/*', source) {
return new Promise((resolve, reject) => {
// Create temporary input element
const element = document.createElement('input');
// Assign properties to element.
element.removed = false;
element.type = 'file';
element.id = 'addAttach';
element.multiple = multiple;
element.accept = contentType;
if (source) { // Needed for file fetch to work on iOS
element.capture = source;
}
// Hide element
element.style.display = 'none';
// Register what happens when element content has changed
element.addEventListener('change', ({ target }) => {
const filesObj = Array.from(target.files);
const allFilesFit = filesObj.every(file => file.size <= maxFileSize);
if (!allFilesFit) {
reject(`Files cannot be bigger than ${maxFileSize / (1024 * 1024)}MB.`);
}
const processes = filesObj.map(fileObj => new Promise(resolveInner => {
const webworkerReader = new FileReader();
webworkerReader.onload = () => {
const base64Str = webworkerReader.result;
resolveInner(base64Str);
};
webworkerReader.readAsDataURL(fileObj);
}));
Promise.all(processes).then(values => {
resolve(values);
});
// Once file content is retrieved, destroy temporary input element
element.onblur = null;
if (!element.removed) {
element.removed = true;
element.remove();
}
});
// Append element to DOM.
document.querySelector('body').appendChild(element);
// Force click
element.click();
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment