-
Notifications
You must be signed in to change notification settings - Fork 70
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add ExternalReader that delegates all reading to an external function #57
base: master
Are you sure you want to change the base?
Conversation
@MikeKovarik Just popping in to say that we’ve been using this code in production for a couple weeks now, and have used it to process more than 200,000 TIFF images of various sizes from 100MB up to almost 4GB. It’s been rock solid and remarkably fast. |
Hello @mbklein. I'm so sorry for responding this late. Glad to hear it's working for you. It's impressive! I actually saw the PR on the day you submitted it and was about to merge it right away. You've hit a great idea with the Anyway, back to the My idea is to implemented custom reader class and add it to exifrs plugin mechanism. This way, I could also just ship the aws parser. Maybe I could finally turn exifr into monorepo and break it up into sepate packages like So this is the API I came up with but am open to suggestions. import exifr from '../src/bundles/full.mjs'
export class ExternalReader extends exifr.ChunkedReader {
async readWhole() {
this.chunked = false
let arrayBuffer = await this._read()
this._swapArrayBuffer(arrayBuffer)
}
async _readChunk(offset, length) {
let abChunk = await this._read(offset, length)
let bytesRead = abChunk.byteLength
if (bytesRead !== length) this.size = offset + bytesRead
return this.set(abChunk, offset, true)
}
}
class AwsReader extends ExternalReader {
static canHandle(input) {
return input !== undefined
&& typeof input.Bucket === 'string'
&& typeof input.Key === 'string'
}
_read(offset, length) {
// the aws code here
}
}
exifr.use(AwsReader)
// or
fileReaders.set('aws', AwsReader)
exifr.parse({ Bucket: "my-aws-bucket", Key: "path/to/some.tif" })
.then(console.log)
.catch(console.error) For now it's still open to changes since I'm still changing the logic of PS: This is out of the topic now, but another thing that delayed me was exploring other ways of making UrlFetcher work in nodejs. I ended up with simple shim of let httpPromise = dynamicImport('http', http => http)
let httpsPromise = dynamicImport('https', https => https)
let fetch = platform.g.fetch || function(url, {headers}) {
let {port, hostname, pathname, protocol} = new URL(url)
const options = {
method: 'GET',
hostname,
path: encodeURI(pathname),
headers
}
if (port !== '') options.port = Number(port)
return new Promise(async (resolve, reject) => {
let lib = protocol === 'https:' ? await httpsPromise : await httpPromise
const req = lib.request(options, res => {
resolve({
status: res.statusCode,
arrayBuffer: () => new Promise(resolveAb => {
let buffers = []
res.on('data', buffer => buffers.push(buffer))
res.on('end', () => resolveAb(concatBuffers(buffers)))
})
})
})
req.on('error', reject)
req.end()
})
} |
I really like where you've gone with this, especially the idea of breaking up the repo and allowing people to require only the bits they need. It would certainly make it way easier to extend – just write and release a module! – over the current all-in-one. One small suggestion I have would be to allow the caller to pass the name of a registered |
Hi @MikeKovarik – just thought I'd check in and see if there's anything I can do to help with where you'd like this PR/issue/refactor to go. Our application is chugging along nicely here using our fork, but it'd be great to get back to the main release at some point. |
Any news on this? 🤓 |
Description
This PR adds an option,
externalReader
, which takes over the task of reading files/chunks from the built-in readers.Example
In the following example, the input to exifr is an object pointing to a file stored in an Amazon S3 bucket. The custom reader function uses the AWS SDK to grab the chunks exifr needs. With this functionality, the input given to exifr can be literally anything, as long as the supplied
externalReader
function knows what to do with it.