11import { NextResponse } from "next/server" ;
2- import { PDFDocument } from "pdf-lib" ;
32import { connectToDatabase } from "@/lib/mongoose" ;
43import { PaperAdmin } from "@/db/papers" ;
5- import { Storage } from "@google-cloud/storage" ;
4+ import { createPDFfromImages } from "@/lib/pdf" ;
5+ import { uploadPDF , uploadThumbnail } from "@/lib/storage" ;
66
7- interface GCPCredentials {
8- type : string ;
9- project_id : string ;
10- private_key_id : string ;
11- private_key : string ;
12- client_email : string ;
13- client_id : string ;
14- auth_uri : string ;
15- token_uri : string ;
16- auth_provider_x509_cert_url : string ;
17- client_x509_cert_url : string ;
18- universe_domain ?: string ;
19- }
20-
21- // Initialize GCP Storage
22- const credentials : GCPCredentials = JSON . parse (
23- process . env . GOOGLE_APPLICATION_CREDENTIALS_JSON ?? "{}" ,
24- ) as GCPCredentials ;
25-
26- const storage = new Storage ( {
27- projectId : process . env . GOOGLE_CLOUD_PROJECT ,
28- credentials,
29- } ) ;
30-
31- const bucketName = process . env . GOOGLE_CLOUD_BUCKET ?? "" ;
32- const bucket = storage . bucket ( bucketName ) ;
7+ export const runtime = "nodejs" ;
338
349export async function POST ( req : Request ) {
3510 try {
3611 await connectToDatabase ( ) ;
37-
3812 const formData = await req . formData ( ) ;
39- const files = formData . getAll ( "files" ) as File [ ] ;
13+ const files = formData . getAll ( "files" ) . filter ( Boolean ) as File [ ] ;
4014 const isPdf = formData . get ( "isPdf" ) === "true" ;
4115 const thumb = formData . get ( "thumbnail" ) as File | null ;
4216
43- console . log ( "Received thumbnail:" , thumb ? thumb . name : "NULL" ) ;
44-
45-
46- if ( ! files || files . length === 0 ) {
47- return NextResponse . json ( { error : "No files received." } , { status : 400 } ) ;
17+ if ( files . length === 0 ) {
18+ return NextResponse . json (
19+ { error : "No files received." } ,
20+ { status : 400 } ,
21+ ) ;
4822 }
4923
50- let pdfBytes : ArrayBuffer ;
51- if ( isPdf && files [ 0 ] ) {
52- pdfBytes = await files [ 0 ] . arrayBuffer ( ) ;
24+ let pdfBytes : Uint8Array ;
25+ if ( isPdf ) {
26+ if ( ! files [ 0 ] ) {
27+ return NextResponse . json (
28+ { error : "No PDF file provided." } ,
29+ { status : 400 } ,
30+ ) ;
31+ }
32+ pdfBytes = new Uint8Array ( await files [ 0 ] . arrayBuffer ( ) ) ;
5333 } else {
5434 pdfBytes = await createPDFfromImages ( files ) ;
5535 }
5636
57- const { file_url, thumbnail_url } = await uploadToGCS ( pdfBytes , thumb ) ;
37+ const buffer = Buffer . from ( pdfBytes ) ;
38+
39+ const file_url = await uploadPDF ( buffer ) ;
40+
41+ let thumbnail_url : string | null = null ;
42+ if ( thumb ) {
43+ const thumbBuffer = Buffer . from ( await thumb . arrayBuffer ( ) ) ;
44+ thumbnail_url = await uploadThumbnail ( thumbBuffer , file_url ) ;
45+ }
5846
59- // Save in MongoDB
6047 const paper = new PaperAdmin ( {
6148 file_url,
6249 thumbnail_url,
50+ campus : formData . get ( "campus" ) ,
6351 subject : null ,
6452 slot : null ,
6553 year : null ,
6654 exam : null ,
6755 semester : null ,
68- campus : formData . get ( "campus" ) ,
6956 ambiguous_tags : [ ] ,
7057 } ) ;
7158 await paper . save ( ) ;
@@ -82,53 +69,3 @@ export async function POST(req: Request) {
8269 ) ;
8370 }
8471}
85-
86- async function uploadToGCS ( bytes : ArrayBuffer , thumbFile ?: File | null ) {
87- const buffer = Buffer . from ( bytes ) ;
88-
89- const pdfFilename = `papers/${ Date . now ( ) } -${ Math . random ( )
90- . toString ( 36 )
91- . substring ( 2 ) } .pdf`;
92- await bucket . file ( pdfFilename ) . save ( buffer , {
93- resumable : false ,
94- contentType : "application/pdf" ,
95- } ) ;
96- const file_url = `https://storage.googleapis.com/${ bucketName } /${ pdfFilename } ` ;
97-
98- let thumbnail_url : string | null = null ;
99- if ( thumbFile ) {
100- const thumbBuffer = Buffer . from ( await thumbFile . arrayBuffer ( ) ) ;
101- const thumbFilename = pdfFilename . replace ( ".pdf" , ".png" ) ;
102- await bucket . file ( thumbFilename ) . save ( thumbBuffer , {
103- resumable : false ,
104- contentType : "image/png" ,
105- } ) ;
106- thumbnail_url = `https://storage.googleapis.com/${ bucketName } /${ thumbFilename } ` ;
107- }
108-
109- return { file_url, thumbnail_url } ;
110- }
111-
112- async function createPDFfromImages ( files : File [ ] ) {
113- const pdfDoc = await PDFDocument . create ( ) ;
114-
115- for ( const file of files ) {
116- const imgBytes = Buffer . from ( await file . arrayBuffer ( ) ) ;
117- let img ;
118- if ( file . type === "image/png" ) {
119- img = await pdfDoc . embedPng ( imgBytes ) ;
120- } else if ( file . type === "image/jpeg" || file . type === "image/jpg" ) {
121- img = await pdfDoc . embedJpg ( imgBytes ) ;
122- } else continue ;
123-
124- const page = pdfDoc . addPage ( [ img . width , img . height ] ) ;
125- page . drawImage ( img , { x : 0 , y : 0 , width : img . width , height : img . height } ) ;
126- }
127-
128- const mergedPdfBytes = await pdfDoc . save ( ) ;
129- const ab = new ArrayBuffer ( mergedPdfBytes . byteLength ) ;
130- new Uint8Array ( ab ) . set ( mergedPdfBytes ) ;
131- return ab ;
132- }
133-
134- export const runtime = "nodejs" ;
0 commit comments