diff --git a/imports/lib/blob/blobFromDataURL.ts b/imports/lib/blob/blobFromDataURL.ts new file mode 100644 index 000000000..1ab1e4a23 --- /dev/null +++ b/imports/lib/blob/blobFromDataURL.ts @@ -0,0 +1,6 @@ +const blobFromDataURL = async (url: string): Promise => { + const response = await fetch(url); + return response.blob(); +}; + +export default blobFromDataURL; diff --git a/imports/lib/blob/blobToDataURL.ts b/imports/lib/blob/blobToDataURL.ts new file mode 100644 index 000000000..b6cbcaecf --- /dev/null +++ b/imports/lib/blob/blobToDataURL.ts @@ -0,0 +1,39 @@ +const _blobToDataURLClient = async (blob: Blob): Promise => + new Promise((resolve, reject) => { + const reader = new FileReader(); + reader.addEventListener('load', (_e) => { + resolve(reader.result as string); + }); + + reader.addEventListener('error', (_e) => { + reject(reader.error); + }); + + reader.addEventListener('abort', (_e) => { + reject(new Error('Read aborted')); + }); + reader.readAsDataURL(blob); + }); + +const _blobToDataURLServer = async (blob: Blob): Promise => { + const mimeType = blob.type; + if (mimeType === '') { + throw new Error('unknown mime-type'); + } + + const arrayBuffer = await blob.arrayBuffer(); + + const {Buffer} = await import('buffer'); + const buffer = Buffer.from(arrayBuffer); + + const base64 = buffer.toString('base64'); + + const {default: dataURL} = await import('../dataURL'); + return dataURL(mimeType, base64); +}; + +const blobToDataURL = Meteor.isServer + ? _blobToDataURLServer + : _blobToDataURLClient; + +export default blobToDataURL; diff --git a/imports/lib/blob/dataURL.tests.ts b/imports/lib/blob/dataURL.tests.ts new file mode 100644 index 000000000..4328d3bcd --- /dev/null +++ b/imports/lib/blob/dataURL.tests.ts @@ -0,0 +1,26 @@ +// eslint-disable-next-line import/no-unassigned-import +import 'regenerator-runtime/runtime.js'; + +import {assert} from 'chai'; + +import {isomorphic} from '../../_test/fixtures'; +import {randomPNGDataURI} from '../../_test/png'; + +import blobFromDataURL from './blobFromDataURL'; +import blobToDataURL from './blobToDataURL'; + +isomorphic(__filename, () => { + it('should allow to convert back and forth from a dataURL', async () => { + if (Meteor.isServer) { + await import('../../../server/polyfill/fetch'); + } + + const url = randomPNGDataURI(); + + const blob = await blobFromDataURL(url); + assert.instanceOf(blob, Blob); + + const result = await blobToDataURL(blob); + assert.equal(result, url); + }); +});