diff --git a/README.md b/README.md index 0288f53..1704db1 100644 --- a/README.md +++ b/README.md @@ -625,10 +625,17 @@ Default: `5` Max amount of subsequent chunks allowed to read in which exifr searches for data segments and blocks. I.e. failsafe that prevents from reading the whole file if it does not contain all of the segments or blocks requested in `options`. -This limit is bypassed if multi-segment segments ocurs in the file and if [`options.multiSegment`](#optionsmultisegment) allows reading all of them. +This limit is bypassed if multi-segment segments occurs in the file and if [`options.multiSegment`](#optionsmultisegment) allows reading all of them. *If the exif isn't found within N chunks (64\*5 = 320KB) it probably isn't in the file and it's not worth reading anymore.* +#### `options.externalReader` +Type: `function` +
+Default: `undefined` + +Async function that receives three parameters - `input`, `offset`, and `length` – and returns an `ArrayBuffer` containing the requested chunk from the input source. If `offset` is missing, `undefined`, or `null`, the function should return the whole file. + ### Output format #### `options.mergeOutput` diff --git a/index.d.ts b/index.d.ts index 5cf47bc..0ea75f2 100644 --- a/index.d.ts +++ b/index.d.ts @@ -44,6 +44,7 @@ interface Options extends FormatOptions { firstChunkSize?: number, chunkSize?: number, chunkLimit?: number, + externalReader?: function, } interface IRotation { diff --git a/src/bundles/lite.mjs b/src/bundles/lite.mjs index 0f336e4..11b2951 100644 --- a/src/bundles/lite.mjs +++ b/src/bundles/lite.mjs @@ -6,6 +6,7 @@ export default mini // File Readers import '../file-readers/UrlFetcher.mjs' import '../file-readers/BlobReader.mjs' +import '../file-readers/ExternalReader.mjs' // File Parser import '../file-parsers/jpeg.mjs' diff --git a/src/file-readers/ExternalReader.mjs b/src/file-readers/ExternalReader.mjs new file mode 100644 index 0000000..d616ed0 --- /dev/null +++ b/src/file-readers/ExternalReader.mjs @@ -0,0 +1,22 @@ +import {fileReaders} from '../plugins.mjs' +import {ChunkedReader} from './ChunkedReader.mjs' + +export class ExternalReader extends ChunkedReader { + + async readWhole() { + this.chunked = false + let arrayBuffer = await this.options.externalReader(this.input) + this._swapArrayBuffer(arrayBuffer) + } + + async _readChunk(offset, length) { + let abChunk = await this.options.externalReader(this.input, offset, length) + if (typeof abChunk === 'undefined') return undefined + let bytesRead = abChunk.byteLength + if (bytesRead !== length) this.size = offset + bytesRead + return this.set(abChunk, offset, true) + } + +} + +fileReaders.set('external', ExternalReader) \ No newline at end of file diff --git a/src/reader.mjs b/src/reader.mjs index 9937452..1b5634c 100644 --- a/src/reader.mjs +++ b/src/reader.mjs @@ -9,7 +9,9 @@ import {fileReaders} from './plugins.mjs' const INVALID_INPUT = 'Invalid input argument' export function read(arg, options) { - if (typeof arg === 'string') + if (options.externalReader && (typeof options.externalReader === 'function')) + return callReaderClass(arg, options, 'external') + else if (typeof arg === 'string') return readString(arg, options) else if (platform.browser && !platform.worker && arg instanceof HTMLImageElement) return readString(arg.src, options) diff --git a/test/reader.spec.mjs b/test/reader.spec.mjs index 82f8215..c33d6c6 100644 --- a/test/reader.spec.mjs +++ b/test/reader.spec.mjs @@ -76,6 +76,20 @@ describe('reader', () => { assert.isObject(output, `output is undefined`) }) + it(`ExternalReader`, async() => { + let called; + + const externalReader = async (input, offset, length) => { + called = {input, offset, length}; + let buffer = await getFile(input); + return buffer.slice(offset, length); + } + + var output = await exifr.parse('IMG_20180725_163423.jpg', {externalReader}) + assert.isObject(output, `output is undefined`) + assert.isObject(called) + }) + isNode && it(`Node: Buffer`, async () => { var buffer = await fs.readFile(getPath('IMG_20180725_163423.jpg')) var output = await exifr.parse(buffer)