first commit
This commit is contained in:
81
app/lib/r2-storage.ts
Normal file
81
app/lib/r2-storage.ts
Normal file
@@ -0,0 +1,81 @@
|
||||
import { S3Client, PutObjectCommand, DeleteObjectCommand, GetObjectCommand } from "@aws-sdk/client-s3";
|
||||
|
||||
// R2 configuration
|
||||
const R2_ACCOUNT_ID = process.env.R2_ACCOUNT_ID || "";
|
||||
const R2_ACCESS_KEY_ID = process.env.R2_ACCESS_KEY_ID || "";
|
||||
const R2_SECRET_ACCESS_KEY = process.env.R2_SECRET_ACCESS_KEY || "";
|
||||
const R2_BUCKET_NAME = process.env.R2_BUCKET_NAME || "";
|
||||
const R2_PUBLIC_URL = process.env.R2_PUBLIC_URL || "";
|
||||
|
||||
// S3 client configuration for Cloudflare R2
|
||||
const s3Client = new S3Client({
|
||||
region: "auto",
|
||||
endpoint: `https://${R2_ACCOUNT_ID}.eu.r2.cloudflarestorage.com`,
|
||||
credentials: {
|
||||
accessKeyId: R2_ACCESS_KEY_ID,
|
||||
secretAccessKey: R2_SECRET_ACCESS_KEY,
|
||||
},
|
||||
});
|
||||
|
||||
export interface UploadOptions {
|
||||
buffer: Buffer;
|
||||
fileName: string;
|
||||
contentType: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Upload a file to R2
|
||||
*/
|
||||
export async function uploadToR2(options: UploadOptions): Promise<string> {
|
||||
const { buffer, fileName, contentType } = options;
|
||||
|
||||
try {
|
||||
const command = new PutObjectCommand({
|
||||
Bucket: R2_BUCKET_NAME,
|
||||
Key: fileName,
|
||||
Body: buffer,
|
||||
ContentType: contentType,
|
||||
});
|
||||
|
||||
await s3Client.send(command);
|
||||
|
||||
// Return the public URL
|
||||
return `${R2_PUBLIC_URL}/${fileName}`;
|
||||
} catch (error) {
|
||||
console.error("R2 upload error:", error);
|
||||
throw new Error(`R2'ye yükleme başarısız: ${error}`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a file from R2
|
||||
*/
|
||||
export async function deleteFromR2(fileName: string): Promise<void> {
|
||||
try {
|
||||
const command = new DeleteObjectCommand({
|
||||
Bucket: R2_BUCKET_NAME,
|
||||
Key: fileName,
|
||||
});
|
||||
|
||||
await s3Client.send(command);
|
||||
} catch (error) {
|
||||
console.error("R2 delete error:", error);
|
||||
throw new Error(`R2'den silme başarısız: ${error}`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get content type from file extension
|
||||
*/
|
||||
export function getContentType(format: string): string {
|
||||
const contentTypeMap: Record<string, string> = {
|
||||
jpg: "image/jpeg",
|
||||
jpeg: "image/jpeg",
|
||||
png: "image/png",
|
||||
gif: "image/gif",
|
||||
webp: "image/webp",
|
||||
avif: "image/avif",
|
||||
};
|
||||
|
||||
return contentTypeMap[format] || "application/octet-stream";
|
||||
}
|
||||
Reference in New Issue
Block a user