@tokenizer/s3
Version:
Amazon S3 tokenizer
63 lines • 2.15 kB
JavaScript
import { parseContentRange } from '@tokenizer/range';
import { GetObjectCommand } from '@aws-sdk/client-s3';
import { Readable } from 'node:stream';
/**
* Use S3-client to execute actual HTTP-requests.
*/
export class S3Request {
constructor(s3, objRequest) {
this.s3 = s3;
this.objRequest = objRequest;
this.abortController = new AbortController();
}
/**
* Concatenate given array of Uint8Arrays
* @param arrays Array of Uint8Arrays
*/
static mergeUint8Arrays(...arrays) {
const totalSize = arrays.reduce((acc, e) => acc + e.length, 0);
const merged = new Uint8Array(totalSize);
arrays.forEach((array, i, arrays) => {
const offset = arrays.slice(0, i).reduce((acc, e) => acc + e.length, 0);
merged.set(array, offset);
});
return merged;
}
async buildArrayBuffer(response) {
const buffers = [];
if (response.Body instanceof Readable) {
for await (const chunk of response.Body) {
buffers.push(chunk);
}
return S3Request.mergeUint8Arrays(...buffers);
}
throw new Error('body expected to be an instance of Readable ');
}
async getResponse(method, range) {
const response = await this.getRangedRequest(range);
const contentRange = parseContentRange(response.ContentRange);
return {
size: contentRange?.instanceLength,
mimeType: response.ContentType,
contentRange,
acceptPartialRequests: true,
arrayBuffer: () => this.buildArrayBuffer(response),
};
}
/**
* Do a ranged request
* @param range Range request
*/
getRangedRequest(range) {
const rangedRequest = {
...this.objRequest,
Range: `bytes=${range[0]}-${range[1]}`,
};
const command = new GetObjectCommand(rangedRequest);
return this.s3.send(command, { abortSignal: this.abortController.signal });
}
abort() {
this.abortController.abort();
}
}
//# sourceMappingURL=s3-request.js.map