Skip to content

Commit 0eefebc

Browse files
Merge pull request #46 from abhitrueprogrammer/staging
Changed upload logic to be more robust
2 parents 8f17a1b + 4754f52 commit 0eefebc

File tree

6 files changed

+262
-187
lines changed

6 files changed

+262
-187
lines changed

src/app/api/mail/route.ts

Lines changed: 0 additions & 117 deletions
This file was deleted.

src/app/api/upload/route.ts

Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
import { NextRequest, NextResponse } from "next/server";
2+
import { PDFDocument } from "pdf-lib";
3+
4+
import { connectToDatabase } from "@/lib/mongoose";
5+
import cloudinary from "cloudinary";
6+
import {
7+
8+
CloudinaryUploadResult,
9+
} from "@/interface";
10+
import Paper from "@/db/papers";
11+
// TODO: REMOVE THUMBNAIL FROM admin-buffer DB
12+
cloudinary.v2.config({
13+
cloud_name: process.env.NEXT_PUBLIC_CLOUDINARY_CLOUD_NAME,
14+
api_key: process.env.CLOUDINARY_API_KEY,
15+
api_secret: process.env.CLOUDINARY_SECRET,
16+
});
17+
18+
export async function POST(req: Request) {
19+
try {
20+
if (!process.env.NEXT_PUBLIC_CLOUDINARY_UPLOAD_PRESET) {
21+
return NextResponse.json({ message: "ServerMisconfig" }, { status: 500 });
22+
}
23+
const uploadPreset = process.env.NEXT_PUBLIC_CLOUDINARY_UPLOAD_PRESET;
24+
const formData = await req.formData();
25+
const files: File[] = formData.getAll("files") as File[];
26+
27+
const subject = formData.get("subject") as string;
28+
const slot = formData.get("slot") as string;
29+
const year = formData.get("year") as string;
30+
const exam = formData.get("exam") as string;
31+
const isPdf = formData.get("isPdf") === "true"; // Convert string to boolean
32+
33+
await connectToDatabase();
34+
let finalUrl: string | undefined = "";
35+
let public_id_cloudinary: string | undefined = "";
36+
let thumbnailUrl: string | undefined = "";
37+
38+
if (!files || files.length === 0) {
39+
return NextResponse.json(
40+
{ error: "No files received." },
41+
{ status: 400 },
42+
);
43+
}
44+
if (!isPdf) {
45+
try {
46+
if (!process.env.NEXT_PUBLIC_CLOUDINARY_UPLOAD_PRESET) {
47+
return;
48+
}
49+
50+
const mergedPdfBytes = await CreatePDF(files);
51+
[public_id_cloudinary, finalUrl] = await uploadPDFFile(mergedPdfBytes, uploadPreset);
52+
} catch (error) {
53+
return NextResponse.json(
54+
{ error: "Failed to process PDF" },
55+
{ status: 500 },
56+
);
57+
}
58+
} else {
59+
[public_id_cloudinary, finalUrl] = await uploadPDFFile(files[0] as File, uploadPreset);
60+
}
61+
const thumbnailResponse = cloudinary.v2.image(finalUrl!, {
62+
format: "jpg",
63+
});
64+
thumbnailUrl = thumbnailResponse
65+
.replace("pdf", "jpg")
66+
.replace("upload", "upload/w_400,h_400,c_fill")
67+
.replace(/<img src='|'\s*\/>/g, "");
68+
const paper = new Paper({
69+
70+
public_id_cloudinary,
71+
finalUrl,
72+
thumbnailUrl,
73+
subject,
74+
slot,
75+
year,
76+
exam,
77+
});
78+
await paper.save();
79+
return NextResponse.json(
80+
{ status: "success", url: finalUrl, thumbnailUrl: thumbnailUrl },
81+
{ status: 201 },
82+
);
83+
} catch (error) {
84+
console.error(error);
85+
return NextResponse.json(
86+
{ message: "Failed to upload papers", error },
87+
88+
{ status: 500 },
89+
);
90+
}
91+
}
92+
93+
94+
async function uploadPDFFile(file: File | ArrayBuffer, uploadPreset: string) {
95+
let bytes;
96+
if(file instanceof File) //for pdf
97+
{
98+
bytes = await file.arrayBuffer();
99+
}
100+
else // for images that are pdf
101+
{
102+
bytes = file as ArrayBuffer;
103+
}
104+
return uploadFile(bytes, uploadPreset, "application/pdf")
105+
}
106+
async function uploadFile(bytes: ArrayBuffer, uploadPreset: string, fileType: string) {
107+
try {
108+
const buffer = Buffer.from(bytes);
109+
const dataUrl = `data:${fileType};base64,${buffer.toString("base64")}`;
110+
111+
const uploadResult: CloudinaryUploadResult =
112+
await cloudinary.v2.uploader.unsigned_upload(dataUrl, uploadPreset);
113+
return [uploadResult.public_id, uploadResult.secure_url ];
114+
} catch (e) {
115+
throw (e);
116+
}
117+
}
118+
async function CreatePDF(files: File[]) {
119+
const pdfDoc = await PDFDocument.create();
120+
121+
const orderedFiles = Array.from(files).sort((a, b) => {
122+
return a.name.localeCompare(b.name);
123+
});
124+
125+
for (const file of orderedFiles) {
126+
const fileBlob = new Blob([file]);
127+
const imgBytes = Buffer.from(await fileBlob.arrayBuffer());
128+
let img;
129+
if (file instanceof File) {
130+
if (file.type === "image/png") {
131+
img = await pdfDoc.embedPng(imgBytes);
132+
} else if (file.type === "image/jpeg" || file.type === "image/jpg") {
133+
img = await pdfDoc.embedJpg(imgBytes);
134+
} else {
135+
continue;
136+
}
137+
const page = pdfDoc.addPage([img.width, img.height]);
138+
page.drawImage(img, {
139+
x: 0,
140+
y: 0,
141+
width: img.width,
142+
height: img.height,
143+
});
144+
}
145+
}
146+
147+
const mergedPdfBytes = await pdfDoc.save();
148+
return mergedPdfBytes;
149+
}

0 commit comments

Comments
 (0)