@@ -3,7 +3,7 @@ import { v2 as cloudinary, UploadApiResponse } from "cloudinary";
33import ImageTracer from "imagetracerjs" ;
44import { NextResponse } from "next/server" ;
55import fetch from "node-fetch" ;
6- import { PNG } from "pngjs " ;
6+ import sharp from "sharp " ;
77
88cloudinary . config ( {
99 cloud_name : process . env . CLOUDINARY_CLOUD_NAME ! ,
@@ -17,44 +17,67 @@ async function cloudinaryToSVG(imageUrl: string, options = { scale: 5 }) {
1717 throw new Error ( `Failed to fetch image: ${ response . statusText } ` ) ;
1818 const buffer = Buffer . from ( await response . arrayBuffer ( ) ) ;
1919
20- const png = PNG . sync . read ( buffer ) ;
20+ const image = sharp ( buffer ) . ensureAlpha ( ) ; // ensures RGBA format
21+ const { width, height } = await image . metadata ( ) ;
22+
23+ if ( ! width || ! height ) {
24+ throw new Error ( "Unable to read image metadata." ) ;
25+ }
26+
27+ const raw = await image . raw ( ) . toBuffer ( ) ;
2128
2229 const myImageData = {
23- width : png . width ,
24- height : png . height ,
25- data : png . data ,
30+ width,
31+ height,
32+ data : raw ,
2633 } ;
2734
2835 const svgstring = ImageTracer . imagedataToSVG ( myImageData , options ) ;
2936 return svgstring ;
3037}
3138
3239export async function POST ( req : Request ) {
33- const formData = await req . formData ( ) ;
34- const file = formData . get ( "image" ) as File ;
40+ try {
41+ const formData = await req . formData ( ) ;
42+ const file = formData . get ( "image" ) as File ;
3543
36- if ( ! file ) {
37- return NextResponse . json ( { error : "No file uploaded" } , { status : 400 } ) ;
38- }
44+ if ( ! file ) {
45+ return NextResponse . json ( { error : "No file uploaded" } , { status : 400 } ) ;
46+ }
3947
40- // Read file as buffer
41- const bytes = await file . arrayBuffer ( ) ;
42- const buffer = Buffer . from ( bytes ) ;
43-
44- const cloudinaryResponse : UploadApiResponse = await new Promise (
45- ( resolve , reject ) => {
46- const uploadStream = cloudinary . uploader . upload_stream ( ( err , result ) => {
47- if ( err || ! result ) return reject ( err ) ;
48- resolve ( result ) ;
49- } ) ;
50- uploadStream . end ( buffer ) ;
51- } ,
52- ) ;
53-
54- const svgString = await cloudinaryToSVG ( cloudinaryResponse . secure_url ) ;
55-
56- return NextResponse . json (
57- { url : cloudinaryResponse . secure_url , svg : svgString , success : true } ,
58- { status : 201 } ,
59- ) ;
48+ const bytes = await file . arrayBuffer ( ) ;
49+ const buffer = Buffer . from ( bytes ) ;
50+
51+ const cloudinaryResponse : UploadApiResponse = await new Promise (
52+ ( resolve , reject ) => {
53+ const uploadStream = cloudinary . uploader . upload_stream (
54+ { resource_type : "image" } ,
55+ ( err , result ) => {
56+ if ( err || ! result ) return reject ( err ) ;
57+ resolve ( result ) ;
58+ } ,
59+ ) ;
60+ uploadStream . end ( buffer ) ;
61+ } ,
62+ ) ;
63+
64+ const svgString = await cloudinaryToSVG ( cloudinaryResponse . secure_url ) ;
65+
66+ return NextResponse . json (
67+ {
68+ url : cloudinaryResponse . secure_url ,
69+ svg : svgString ,
70+ success : true ,
71+ } ,
72+ { status : 201 } ,
73+ ) ;
74+ } catch ( err : unknown ) {
75+ console . error ( "Upload error:" , err ) ;
76+ const errorMessage =
77+ err instanceof Error ? err . message : "Internal Server Error" ;
78+ return NextResponse . json (
79+ { success : false , error : errorMessage } ,
80+ { status : 500 } ,
81+ ) ;
82+ }
6083}
0 commit comments