54 lines
1.6 KiB
TypeScript
54 lines
1.6 KiB
TypeScript
import { auth } from "@clerk/nextjs/server";
|
|
import { ContractService } from "@/lib/services/contract.service";
|
|
|
|
const sanitizeFilename = (fileName: string): string => {
|
|
const cleaned = fileName.replace(/[\\/:*?"<>|]/g, "_").trim();
|
|
return cleaned || "contract";
|
|
};
|
|
|
|
export async function GET(
|
|
_: Request,
|
|
{ params }: { params: Promise<{ id: string }> },
|
|
) {
|
|
try {
|
|
const { userId: clerkId } = await auth();
|
|
if (!clerkId) {
|
|
return new Response("Unauthorized", { status: 401 });
|
|
}
|
|
|
|
const { id } = await params;
|
|
if (!id) {
|
|
return new Response("Missing contract ID", { status: 400 });
|
|
}
|
|
|
|
const contract = await ContractService.getById(id);
|
|
|
|
const upstream = await fetch(contract.fileUrl);
|
|
if (!upstream.ok) {
|
|
return new Response("Unable to fetch source file", { status: 502 });
|
|
}
|
|
|
|
const bytes = await upstream.arrayBuffer();
|
|
const contentType =
|
|
contract.mimeType ||
|
|
upstream.headers.get("content-type") ||
|
|
"application/octet-stream";
|
|
const fileName = sanitizeFilename(contract.fileName);
|
|
const encodedFileName = encodeURIComponent(fileName);
|
|
|
|
return new Response(bytes, {
|
|
status: 200,
|
|
headers: {
|
|
"Content-Type": contentType,
|
|
"Content-Disposition": `attachment; filename="${fileName}"; filename*=UTF-8''${encodedFileName}`,
|
|
"Cache-Control": "private, no-store, no-cache, must-revalidate",
|
|
Pragma: "no-cache",
|
|
Expires: "0",
|
|
},
|
|
});
|
|
} catch (error) {
|
|
console.error("Contract download error:", error);
|
|
return new Response("Failed to download contract", { status: 500 });
|
|
}
|
|
}
|