@eleven-am/nestjs-storage
Version:
A NestJS module for uploading files to cloud storage providers
156 lines (141 loc) • 4.13 kB
text/typescript
import { BaseStorage } from './baseStorage';
import { LocalStorageOption } from '../types/options';
import * as path from 'path';
import * as fs from 'fs';
import { IFile, PartialStream } from '../types/storage';
import { getMimeType } from '../lib/getMimetype';
export class LocalStorage extends BaseStorage {
private readonly root: string;
constructor(options: LocalStorageOption) {
super(options.provider);
this.root = options.options.root;
}
createFolder(filePath: string) {
return new Promise<IFile>((resolve, reject) => {
fs.mkdir(filePath, (err) => {
if (err) {
reject(err);
} else {
this.getFileOrFolder(filePath).then(resolve).catch(reject);
}
});
});
}
deleteFileOrFolder(fileId: string) {
return new Promise<boolean>((resolve, reject) => {
fs.unlink(fileId, (err) => {
if (err) {
reject(err);
} else {
resolve(true);
}
});
});
}
getFileOrFolder(filePath: string) {
return new Promise<IFile>((resolve, reject) => {
fs.stat(filePath, (err, stats) => {
if (err) {
reject(err);
} else {
resolve({
size: stats.size,
modifiedAt: stats.mtime,
isFolder: stats.isDirectory(),
name: path.basename(filePath),
path: filePath,
mimeType: stats.isFile() ? getMimeType(filePath) : null,
});
}
});
});
}
moveFileOrFolder(fileId: string, newPath: string) {
return this.renameFileOrFolder(fileId, newPath);
}
putFile(path: string, data: Buffer) {
return new Promise<IFile>((resolve, reject) => {
fs.writeFile(path, data, (err) => {
if (err) {
reject(err);
} else {
this.getFileOrFolder(path).then(resolve).catch(reject);
}
});
});
}
readFile(fileId: string) {
return new Promise<NodeJS.ReadableStream>((resolve, reject) => {
this.getFileOrFolder(fileId)
.then((file) => {
if (file.isFolder) {
reject(new Error('Cannot read a folder'));
} else {
const stream = fs.createReadStream(fileId);
resolve(stream);
}
})
.catch(reject);
});
}
readFolder(folderId: string) {
return new Promise<IFile[]>((resolve, reject) => {
this.getFileOrFolder(folderId)
.then((file) => {
if (!file.isFolder) {
reject(new Error('Cannot read a file'));
} else {
fs.readdir(folderId, (err, files) => {
if (err) {
reject(err);
} else {
Promise.all(
files.map((file) =>
this.getFileOrFolder(path.join(folderId, file)),
),
)
.then(resolve)
.catch(reject);
}
});
}
})
.catch(reject);
});
}
readRootFolder() {
return this.readFolder('/');
}
renameFileOrFolder(fileId: string, newName: string) {
return new Promise<IFile>((resolve, reject) => {
fs.rename(fileId, newName, (err) => {
if (err) {
reject(err);
} else {
this.getFileOrFolder(newName).then(resolve).catch(reject);
}
});
});
}
streamFile(fileId: string, range: string) {
return new Promise<PartialStream>((resolve, reject) => {
this.getFileOrFolder(fileId)
.then((file) => {
if (file.isFolder) {
reject(new Error('Cannot stream a folder'));
} else {
const { start, end, headers } = this.buildRange(range, file);
const stream = fs.createReadStream(fileId, {
start: start,
end: end,
});
resolve({ stream, headers: headers });
}
})
.catch(reject);
});
}
async getSignedUrl(fileId: string): Promise<string> {
throw new Error(`Cannot get signed url for ${fileId} in local storage`);
}
}