| import { S3Client, PutObjectCommand } from '@aws-sdk/client-s3'; | |
| import crypto from 'crypto'; | |
| import path from 'path'; | |
| export async function uploadFile(buffer: Buffer, originalFilename: string, contentType: string): Promise<string> { | |
| const accountId = process.env.R2_ACCOUNT_ID; | |
| const bucket = process.env.R2_BUCKET; | |
| const accessKeyId = process.env.R2_ACCESS_KEY_ID; | |
| const secretAccessKey = process.env.R2_SECRET_ACCESS_KEY; | |
| const publicUrl = process.env.R2_PUBLIC_URL; | |
| if (!accountId || !bucket || !accessKeyId || !secretAccessKey || !publicUrl) { | |
| console.warn('[Storage] R2 not fully configured — returning dummy URL'); | |
| return `https://dummy-storage.com/${originalFilename}`; | |
| } | |
| const ext = path.extname(originalFilename); | |
| const uniqueName = `${crypto.randomUUID()}-${Date.now()}${ext}`; | |
| const client = new S3Client({ | |
| region: 'auto', | |
| endpoint: `https://${accountId}.r2.cloudflarestorage.com`, | |
| credentials: { accessKeyId, secretAccessKey }, | |
| }); | |
| await client.send(new PutObjectCommand({ | |
| Bucket: bucket, | |
| Key: uniqueName, | |
| Body: buffer, | |
| ContentType: contentType, | |
| })); | |
| return `${publicUrl.replace(/\/$/, "")}/${uniqueName}`; | |
| } | |