Use /thumbnail endpoint and add long cache

This commit is contained in:
mbaharip
2024-05-05 23:47:55 +07:00
parent a0441387d0
commit 04439d74ef
+27 -65
View File
@@ -1,4 +1,5 @@
import { NextRequest, NextResponse } from "next/server";
import { z } from "zod";
import { decryptData } from "~/utils/encryptionHelper/hash";
import gdrive from "~/utils/gdriveInstance";
@@ -16,6 +17,14 @@ export async function GET(
{ params: { encryptedId } }: Props,
) {
try {
const searchParams = new URL(request.nextUrl).searchParams;
const size = searchParams.get("size") || "512";
const validSize = z.coerce.number().safeParse(size);
if (!validSize.success) {
throw new Error("Invalid size");
}
const defaultImage = NextResponse.redirect(
new URL("/og.png", config.basePath),
{
@@ -23,86 +32,39 @@ export async function GET(
},
);
const decryptedId = await decryptData(encryptedId);
const _fileMeta = gdrive.files.get({
const fileMeta = await gdrive.files.get({
fileId: decryptedId,
fields:
"id, name, mimeType, fileExtension, webContentLink, thumbnailLink",
supportsAllDrives: config.apiConfig.isTeamDrive,
});
const _fileContent = gdrive.files.get(
{
fileId: decryptedId,
alt: "media",
supportsAllDrives: config.apiConfig.isTeamDrive,
},
{
responseType: "stream",
},
);
const [fileMeta, fileContent] = await Promise.all([
_fileMeta,
_fileContent,
]);
const fileSize = Number(fileMeta.data.size || 0);
if (!fileMeta.data.webContentLink) return defaultImage;
if (!fileMeta.data.thumbnailLink) return defaultImage;
if (
!fileMeta.data.mimeType?.startsWith("image") &&
!fileMeta.data.mimeType?.startsWith("video")
)
return defaultImage;
// If svg, return actual image since there is no thumbnail for svg
if (
fileMeta.data.mimeType?.includes("svg") &&
fileSize <= config.apiConfig.maxFileSize
) {
const fileBuffer = await new Promise<Buffer>((resolve, reject) => {
const chunks: Buffer[] = [];
fileContent.data.on("data", (chunk) => {
chunks.push(chunk);
});
fileContent.data.on("end", () => {
resolve(Buffer.concat(chunks));
});
fileContent.data.on("error", (err) => {
reject(err);
});
});
return new NextResponse(fileBuffer, {
headers: {
"Cache-Control": "public, max-age=31536000, immutable",
"Content-Type": fileMeta.data.mimeType || "application/octet-stream",
"Content-Length": fileBuffer.length.toString(),
"Content-Disposition": `attachment; filename="${encodeURIComponent(
fileMeta.data.name || `Untitled.${fileMeta.data.fileExtension}`,
)}"`,
},
});
return defaultImage;
}
if (config.apiConfig.proxyThumbnail) {
const downloadThumb = await fetch(fileMeta.data.thumbnailLink, {
cache: "force-cache",
});
const buffer = await downloadThumb.arrayBuffer();
const url = `https://drive.google.com/thumbnail?id=${decryptedId}&sz=w${size}`;
return new NextResponse(buffer, {
headers: {
"Cache-Control": "public, max-age=31536000, immutable",
"Content-Type": fileMeta.data.mimeType || "application/octet-stream",
"Content-Length": buffer.byteLength.toString(),
"Content-Disposition": `attachment; filename="${encodeURIComponent(
fileMeta.data.name || `Untitled.${fileMeta.data.fileExtension}`,
)}"`,
},
});
if (!config.apiConfig.proxyThumbnail) {
return NextResponse.redirect(url);
}
return NextResponse.redirect(fileMeta.data.thumbnailLink);
const downloadThumb = await fetch(url, {
cache: "force-cache",
});
const buffer = await downloadThumb.arrayBuffer();
return new NextResponse(buffer, {
headers: {
"Cache-Control": "public, max-age=31536000, immutable",
"Content-Type": "image/jpeg",
"Content-Length": buffer.byteLength.toString(),
},
});
} catch (error) {
const e = error as Error;
console.error(e.message);