mirror of
https://github.com/docmost/docmost.git
synced 2025-11-17 12:31:09 +10:00
Refactoring
* Refactor workspace membership system * Create setup endpoint * Use Passport.js * Several updates and fixes
This commit is contained in:
115
apps/server/src/integrations/storage/drivers/s3.driver.ts
Normal file
115
apps/server/src/integrations/storage/drivers/s3.driver.ts
Normal file
@ -0,0 +1,115 @@
|
||||
import { S3StorageConfig, StorageDriver, StorageOption } from '../interfaces';
|
||||
import {
|
||||
DeleteObjectCommand,
|
||||
GetObjectCommand,
|
||||
HeadObjectCommand,
|
||||
NoSuchKey,
|
||||
PutObjectCommand,
|
||||
S3Client,
|
||||
} from '@aws-sdk/client-s3';
|
||||
import { streamToBuffer } from '../storage.utils';
|
||||
import { Readable } from 'stream';
|
||||
import * as mime from 'mime-types';
|
||||
import { getSignedUrl } from '@aws-sdk/s3-request-presigner';
|
||||
|
||||
export class S3Driver implements StorageDriver {
|
||||
private readonly s3Client: S3Client;
|
||||
private readonly config: S3StorageConfig;
|
||||
|
||||
constructor(config: S3StorageConfig) {
|
||||
this.config = config;
|
||||
this.s3Client = new S3Client(config as any);
|
||||
}
|
||||
|
||||
async upload(filePath: string, file: Buffer): Promise<void> {
|
||||
try {
|
||||
const contentType =
|
||||
mime.contentType(filePath) || 'application/octet-stream';
|
||||
|
||||
const command = new PutObjectCommand({
|
||||
Bucket: this.config.bucket,
|
||||
Key: filePath,
|
||||
Body: file,
|
||||
ContentType: contentType,
|
||||
// ACL: "public-read",
|
||||
});
|
||||
|
||||
await this.s3Client.send(command);
|
||||
// we can get the path from location
|
||||
|
||||
console.log(`File uploaded successfully: ${filePath}`);
|
||||
} catch (error) {
|
||||
throw new Error(`Failed to upload file: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
async read(filePath: string): Promise<Buffer> {
|
||||
try {
|
||||
const command = new GetObjectCommand({
|
||||
Bucket: this.config.bucket,
|
||||
Key: filePath,
|
||||
});
|
||||
|
||||
const response = await this.s3Client.send(command);
|
||||
|
||||
return streamToBuffer(response.Body as Readable);
|
||||
} catch (error) {
|
||||
throw new Error(`Failed to read file from S3: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
async exists(filePath: string): Promise<boolean> {
|
||||
try {
|
||||
const command = new HeadObjectCommand({
|
||||
Bucket: this.config.bucket,
|
||||
Key: filePath,
|
||||
});
|
||||
|
||||
await this.s3Client.send(command);
|
||||
return true;
|
||||
} catch (err) {
|
||||
if (err instanceof NoSuchKey) {
|
||||
return false;
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
getUrl(filePath: string): string {
|
||||
return `${this.config.endpoint}/${this.config.bucket}/${filePath}`;
|
||||
}
|
||||
|
||||
async getSignedUrl(filePath: string, expiresIn: number): Promise<string> {
|
||||
const command = new GetObjectCommand({
|
||||
Bucket: this.config.bucket,
|
||||
Key: filePath,
|
||||
});
|
||||
return await getSignedUrl(this.s3Client, command, { expiresIn });
|
||||
}
|
||||
|
||||
async delete(filePath: string): Promise<void> {
|
||||
try {
|
||||
const command = new DeleteObjectCommand({
|
||||
Bucket: this.config.bucket,
|
||||
Key: filePath,
|
||||
});
|
||||
|
||||
await this.s3Client.send(command);
|
||||
} catch (err) {
|
||||
throw new Error(
|
||||
`Error deleting file ${filePath} from S3. ${err.message}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
getDriver(): S3Client {
|
||||
return this.s3Client;
|
||||
}
|
||||
|
||||
getDriverName(): string {
|
||||
return StorageOption.S3;
|
||||
}
|
||||
|
||||
getConfig(): Record<string, any> {
|
||||
return this.config;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user