File

src/storage/storage.service.ts

Index

Methods

Constructor

constructor()

Methods

Async deleteFile
deleteFile(key: string)
Parameters :
Name Type Optional
key string No
Returns : Promise<void>
Async getSignedDownloadUrl
getSignedDownloadUrl(key: string, expiresIn: number)
Parameters :
Name Type Optional Default value
key string No
expiresIn number No 3600
Returns : Promise<string | null>
Async uploadFile
uploadFile(file: Buffer, originalName: string, mimeType: string, folder: string)
Parameters :
Name Type Optional Default value
file Buffer No
originalName string No
mimeType string No
folder string No 'uploads'
Returns : Promise<literal type | null>
import { Injectable, Logger } from '@nestjs/common';
import {
  S3Client,
  PutObjectCommand,
  GetObjectCommand,
  DeleteObjectCommand,
} from '@aws-sdk/client-s3';
import { getSignedUrl } from '@aws-sdk/s3-request-presigner';
import { v4 as uuid } from 'uuid';

@Injectable()
export class StorageService {
  private readonly logger = new Logger(StorageService.name);
  private s3: S3Client | null = null;
  private bucket: string;

  constructor() {
    this.bucket = process.env.S3_BUCKET || 'fleetcommand-uploads';

    if (process.env.S3_ENDPOINT) {
      this.s3 = new S3Client({
        endpoint: process.env.S3_ENDPOINT,
        region: process.env.S3_REGION || 'us-east-1',
        credentials: {
          accessKeyId: process.env.S3_ACCESS_KEY || '',
          secretAccessKey: process.env.S3_SECRET_KEY || '',
        },
        forcePathStyle: true, // Required for MinIO
      });
      this.logger.log(`S3 storage configured: ${process.env.S3_ENDPOINT}`);
    } else {
      this.logger.warn('S3 not configured — file storage disabled');
    }
  }

  async uploadFile(
    file: Buffer,
    originalName: string,
    mimeType: string,
    folder: string = 'uploads',
  ): Promise<{ key: string; url: string } | null> {
    if (!this.s3) {
      this.logger.warn('S3 not configured — skipping upload');
      return null;
    }

    const key = `${folder}/${uuid()}-${originalName}`;

    await this.s3.send(
      new PutObjectCommand({
        Bucket: this.bucket,
        Key: key,
        Body: file,
        ContentType: mimeType,
      }),
    );

    this.logger.log(`File uploaded: ${key}`);
    return {
      key,
      url: `${process.env.S3_ENDPOINT}/${this.bucket}/${key}`,
    };
  }

  async getSignedDownloadUrl(
    key: string,
    expiresIn: number = 3600,
  ): Promise<string | null> {
    if (!this.s3) return null;

    const command = new GetObjectCommand({
      Bucket: this.bucket,
      Key: key,
    });
    return getSignedUrl(this.s3, command, { expiresIn });
  }

  async deleteFile(key: string): Promise<void> {
    if (!this.s3) return;
    await this.s3.send(
      new DeleteObjectCommand({ Bucket: this.bucket, Key: key }),
    );
    this.logger.log(`File deleted: ${key}`);
  }
}

results matching ""

    No results matching ""