Re_Backend/src/services/cpc-cdc/CpcGcsService.ts
2026-04-17 19:58:45 +05:30

72 lines
2.7 KiB
TypeScript

import { Storage } from "@google-cloud/storage";
import path from 'path';
import logger from "@utils/logger";
/** Optional layout for CPC/CSD objects (mirrors local `uploads/cpc-csd-files/...`). */
export type CpcGcsUploadOptions = {
bucket?: string;
/** Directory prefix inside the bucket, no leading slash, e.g. `cpc-csd/csd/BOOK-1/documents` */
objectDir?: string;
/** Final filename segment only (no path separators) */
objectBaseName?: string;
};
class CpcGcsService {
private storage: Storage;
private bucketName: string;
constructor() {
this.storage = new Storage({
projectId: process.env.GCP_PROJECT_ID,
keyFilename: process.env.GCP_KEY_FILE
});
this.bucketName = process.env.GCP_BUCKET_NAME || '';
}
parseGsUrl(gsUrl: string) {
if (!gsUrl || !gsUrl.startsWith("gs://")) throw new Error("INVALID_DOCUMENT_URL");
const s = gsUrl.slice(5);
const [bucket, ...rest] = s.split("/");
const objectPath = rest.join("/");
if (!bucket || !objectPath) throw new Error("INVALID_DOCUMENT_URL");
return { bucket, objectPath };
}
async downloadFromGcs(gsUrl: string): Promise<Buffer> {
const { bucket, objectPath } = this.parseGsUrl(gsUrl);
const [buf] = await this.storage.bucket(bucket).file(objectPath).download();
return buf;
}
/**
* Third argument can be a legacy custom bucket string, or structured options for path layout.
*/
async uploadToGcs(
fileBuffer: Buffer,
originalName: string,
legacyBucketOrOpts?: string | CpcGcsUploadOptions
): Promise<string> {
const opts: CpcGcsUploadOptions =
typeof legacyBucketOrOpts === 'string' ? { bucket: legacyBucketOrOpts } : legacyBucketOrOpts || {};
const targetBucket = opts.bucket || this.bucketName;
const base =
opts.objectBaseName && !opts.objectBaseName.includes('/') && !opts.objectBaseName.includes('..')
? opts.objectBaseName
: `${Date.now()}-${path.basename(originalName)}`;
const dir =
opts.objectDir && !opts.objectDir.includes('..')
? opts.objectDir.replace(/^\/+|\/+$/g, '')
: 'cpc-csd/uploads';
const fileName = `${dir}/${base}`.replace(/\\/g, '/');
const bucket = this.storage.bucket(targetBucket);
const file = bucket.file(fileName);
await file.save(fileBuffer);
logger.info(`[CpcGcsService] File uploaded to gs://${targetBucket}/${fileName}`);
return `gs://${targetBucket}/${fileName}`;
}
}
export const cpcGcsService = new CpcGcsService();