feat(file): Added functionality to retrieve magic bytes from files and detect file types using magic bytes.

This commit is contained in:
Philipp Kunz 2024-11-18 15:07:46 +01:00
parent c7f0c97341
commit 383a5204f4
7 changed files with 6027 additions and 4273 deletions

View File

@ -1,5 +1,12 @@
# Changelog # Changelog
## 2024-11-18 - 3.1.0 - feat(file)
Added functionality to retrieve magic bytes from files and detect file types using magic bytes.
- Introduced method `getMagicBytes` in `File` and `Bucket` classes to retrieve a specific number of bytes from a file.
- Enhanced file type detection by utilizing magic bytes in `MetaData` class.
- Updated dependencies for better performance and compatibility.
## 2024-11-18 - 3.0.24 - fix(metadata) ## 2024-11-18 - 3.0.24 - fix(metadata)
Fix metadata handling to address type assertion and data retrieval. Fix metadata handling to address type assertion and data retrieval.

View File

@ -19,8 +19,8 @@
"@push.rocks/tapbundle": "^5.3.0" "@push.rocks/tapbundle": "^5.3.0"
}, },
"dependencies": { "dependencies": {
"@aws-sdk/client-s3": "^3.670.0", "@aws-sdk/client-s3": "^3.693.0",
"@push.rocks/smartmime": "^2.0.2", "@push.rocks/smartmime": "^2.0.4",
"@push.rocks/smartpath": "^5.0.18", "@push.rocks/smartpath": "^5.0.18",
"@push.rocks/smartpromise": "^4.0.4", "@push.rocks/smartpromise": "^4.0.4",
"@push.rocks/smartrx": "^3.0.7", "@push.rocks/smartrx": "^3.0.7",

10159
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@ -3,6 +3,6 @@
*/ */
export const commitinfo = { export const commitinfo = {
name: '@push.rocks/smartbucket', name: '@push.rocks/smartbucket',
version: '3.0.24', version: '3.1.0',
description: 'A TypeScript library offering simple and cloud-agnostic object storage with advanced features like bucket creation, file and directory management, and data streaming.' description: 'A TypeScript library offering simple and cloud-agnostic object storage with advanced features like bucket creation, file and directory management, and data streaming.'
} }

View File

@ -232,6 +232,7 @@ export class Bucket {
if (typeArg === 'webstream') { if (typeArg === 'webstream') {
return (await duplexStream.getWebStreams()).readable; return (await duplexStream.getWebStreams()).readable;
} }
throw new Error('unknown typeArg');
} }
/** /**
@ -437,4 +438,28 @@ export class Bucket {
const response = await this.smartbucketRef.s3Client.send(command); const response = await this.smartbucketRef.s3Client.send(command);
return response.Contents.length > 0; return response.Contents.length > 0;
} }
public async getMagicBytes(optionsArg: { path: string; length: number }): Promise<Buffer> {
try {
const command = new plugins.s3.GetObjectCommand({
Bucket: this.name,
Key: optionsArg.path,
Range: `bytes=0-${optionsArg.length - 1}`,
});
const response = await this.smartbucketRef.s3Client.send(command);
const chunks = [];
const stream = response.Body as any; // SdkStreamMixin includes readable stream
for await (const chunk of stream) {
chunks.push(chunk);
}
return Buffer.concat(chunks);
} catch (error) {
console.error(
`Error retrieving magic bytes from object at path '${optionsArg.path}' in bucket '${this.name}':`,
error
);
throw error;
}
}
} }

View File

@ -50,6 +50,10 @@ export class File {
public parentDirectoryRef: Directory; public parentDirectoryRef: Directory;
public name: string; public name: string;
/**
* get the full path to the file
* @returns the full path to the file
*/
public getBasePath(): string { public getBasePath(): string {
return plugins.path.join(this.parentDirectoryRef.getBasePath(), this.name); return plugins.path.join(this.parentDirectoryRef.getBasePath(), this.name);
} }
@ -188,7 +192,7 @@ export class File {
if (isDirectory) { if (isDirectory) {
moveToPath = await helpers.reducePathDescriptorToPath({ moveToPath = await helpers.reducePathDescriptorToPath({
...pathDescriptorArg, ...pathDescriptorArg,
path: plugins.path.join(pathDescriptorArg.path, this.name), path: plugins.path.join(pathDescriptorArg.path!, this.name),
}); });
} }
// lets move the file // lets move the file
@ -230,4 +234,11 @@ export class File {
contents: JSON.stringify(dataArg), contents: JSON.stringify(dataArg),
}); });
} }
public async getMagicBytes(optionsArg: { length: number }): Promise<Buffer> {
return this.parentDirectoryRef.bucketRef.getMagicBytes({
path: this.getBasePath(),
length: optionsArg.length
})
}
} }

View File

@ -31,10 +31,24 @@ export class MetaData {
public async getFileType(optionsArg?: { public async getFileType(optionsArg?: {
useFileExtension?: boolean; useFileExtension?: boolean;
useMagicBytes?: boolean; useMagicBytes?: boolean;
}): Promise<string> { }): Promise<plugins.smartmime.IFileTypeResult | undefined> {
if ((optionsArg && optionsArg.useFileExtension) || optionsArg.useFileExtension === undefined) { if ((optionsArg && optionsArg.useFileExtension) || !optionsArg) {
return plugins.path.extname(this.fileRef.name); const fileType = await plugins.smartmime.detectMimeType({
path: this.fileRef.name,
});
return fileType;
} }
if (optionsArg && optionsArg.useMagicBytes) {
const fileType = await plugins.smartmime.detectMimeType({
buffer: await this.fileRef.getMagicBytes({
length: 100,
})
});
return fileType;
}
throw new Error('optionsArg.useFileExtension and optionsArg.useMagicBytes cannot both be false');
} }
/** /**