File size: 3,098 Bytes
cc276cc
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90

import { NextRequest, NextResponse } from 'next/server';
import { S3Client, PutObjectCommand, GetObjectCommand } from '@aws-sdk/client-s3';

// Hardcoded credentials for stability in this environment
const R2_ACCOUNT_ID = "057488dfeda40a86a3a5d10340c38db3";
const R2_ACCESS_KEY_ID = "60bf8645223f8566982671ee43911238";
const R2_SECRET_ACCESS_KEY = "2f57e4371382dbb8c6128f2d5edd7f24c31ee1c2d4bbcdb0dbdc2d2fe112dd70";
const R2_BUCKET_NAME = "myapp";

// Initialize S3 client directly
const s3 = new S3Client({
  region: 'auto',
  endpoint: `https://${R2_ACCOUNT_ID}.r2.cloudflarestorage.com`,
  credentials: {
    accessKeyId: R2_ACCESS_KEY_ID,
    secretAccessKey: R2_SECRET_ACCESS_KEY,
  },
});


// GET handler now fetches the object and returns it directly
export async function GET(req: NextRequest) {
    try {
        const url = new URL(req.url);
        const fileKey = url.searchParams.get('fileKey');

        if (!fileKey) {
            return NextResponse.json({ error: 'File key is required' }, { status: 400 });
        }

        const command = new GetObjectCommand({
            Bucket: R2_BUCKET_NAME,
            Key: fileKey,
        });

        const { Body, ContentType } = await s3.send(command);

        if (!Body) {
             return NextResponse.json({ error: 'File not found or body is empty' }, { status: 404 });
        }
        
        // Return the file content directly as a readable stream
        return new NextResponse(Body as any, {
            headers: {
                'Content-Type': ContentType || 'application/octet-stream',
            },
        });


    } catch (error: any) {
        console.error('Error fetching file from R2:', error.message);
        // Ensure a JSON error response for client-side error handling
        if (error.name === 'NoSuchKey') {
             return NextResponse.json({ error: 'File not found' }, { status: 404 });
        }
        return NextResponse.json({ error: 'Failed to get file from storage', details: error.message }, { status: 500 });
    }
}
// POST handler for receiving file from client and uploading to R2
export async function POST(req: NextRequest) {
    try {
        const formData = await req.formData();
        const file = formData.get('file') as File | null;

        if (!file) {
            return NextResponse.json({ error: 'File is required' }, { status: 400 });
        }
        
        const buffer = Buffer.from(await file.arrayBuffer());
        const sanitizedFilename = file.name.replace(/[^a-zA-Z0-9._-]/g, '');
        const fileKey = `uploads/user-content/${Date.now()}-${sanitizedFilename}`;
        
        const command = new PutObjectCommand({
            Bucket: R2_BUCKET_NAME,
            Key: fileKey,
            Body: buffer,
            ContentType: file.type,
        });

        await s3.send(command);

        return NextResponse.json({ fileKey });

    } catch (error: any) {
        console.error('Error uploading file:', error.message);
        return NextResponse.json({ error: 'Failed to upload file', details: error.message }, { status: 500 });
    }
}