11import { NextResponse } from 'next/server' ;
22import { getServerSession } from 'next-auth' ;
3- import { handleUpload , type HandleUploadBody } from '@vercel/blob/client' ;
3+ import sharp from 'sharp' ;
4+ import { put } from '@vercel/blob' ;
45
56export async function POST ( request : Request ) : Promise < NextResponse > {
67 const session = await getServerSession ( ) ;
@@ -9,47 +10,48 @@ export async function POST(request: Request): Promise<NextResponse> {
910 return new NextResponse ( 'Unauthorized' , { status : 401 } ) ;
1011 }
1112
12- const body = ( await request . json ( ) ) as HandleUploadBody ;
13-
1413 try {
15- const jsonResponse = await handleUpload ( {
16- body,
17- request,
18- onBeforeGenerateToken : async (
19- pathname
20- /* clientPayload */
21- ) => {
22- return {
23- allowedContentTypes : [ 'image/*' ] ,
24- tokenPayload : JSON . stringify ( {
25- // optional, sent to your server on upload completion
26- // you could pass a user id from auth, or a value from clientPayload
27- } ) ,
28- } ;
29- } ,
30- onUploadCompleted : async ( { blob, tokenPayload } ) => {
31- // Get notified of client upload completion
32- // ⚠️ This will not work on `localhost` websites,
33- // Use ngrok or similar to get the full upload flow
34-
35- console . log ( 'blob upload completed' , blob , tokenPayload ) ;
36-
37- try {
38- // Run any logic after the file upload completed
39- // const { userId } = JSON.parse(tokenPayload);
40- // await db.update({ avatar: blob.url, userId });
41- return ;
42- } catch ( error ) {
43- throw new Error ( 'Could not update user' ) ;
44- }
45- } ,
14+ const formData = await request . formData ( ) ;
15+ const file = formData . get ( 'file' ) as File ;
16+
17+ if ( ! file ) {
18+ return NextResponse . json ( { error : 'No file provided' } , { status : 400 } ) ;
19+ }
20+
21+ if ( ! file . type . startsWith ( 'image/' ) ) {
22+ return NextResponse . json ( { error : 'File must be an image' } , { status : 400 } ) ;
23+ }
24+
25+ const arrayBuffer = await file . arrayBuffer ( ) ;
26+ const buffer = Buffer . from ( arrayBuffer ) ;
27+
28+ const timestamp = Date . now ( ) ;
29+ const baseFilename = file . name . replace ( / \. [ ^ / . ] + $ / , '' ) ;
30+ const pathname = `/images/${ timestamp } -${ baseFilename } .webp` ;
31+
32+ // Convert to WebP with max 1920px width
33+ const webpBuffer = await sharp ( buffer )
34+ . resize ( 1920 , null , {
35+ withoutEnlargement : true ,
36+ fit : 'inside' ,
37+ } )
38+ . webp ( { quality : 85 } )
39+ . toBuffer ( ) ;
40+
41+ const blob = await put ( pathname , webpBuffer , {
42+ access : 'public' ,
43+ contentType : 'image/webp' ,
4644 } ) ;
4745
48- return NextResponse . json ( jsonResponse ) ;
46+ return NextResponse . json ( {
47+ success : true ,
48+ url : blob . url ,
49+ } ) ;
4950 } catch ( error ) {
51+ console . error ( 'Upload error:' , error ) ;
5052 return NextResponse . json (
5153 { error : ( error as Error ) . message } ,
52- { status : 400 } // The webhook will retry 5 times waiting for a 200
54+ { status : 500 }
5355 ) ;
5456 }
5557}
0 commit comments