2e1f4d7929
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
50 lines
1.9 KiB
TypeScript
50 lines
1.9 KiB
TypeScript
import type { NextRequest } from "next/server";
|
||
import { readAttachmentForUser } from "@/features/attachments/service";
|
||
import { getCurrentUser } from "@/lib/dal";
|
||
|
||
/**
|
||
* GET /api/files/:id[?v=thumb][&indir=1] — oturum ve hane yetkisi kontrol edilerek ek dosyayı
|
||
* servis eder. Erişim yoksa (başka hane, gizli hesap, silinmiş kayıt) 404: varlık sızdırılmaz.
|
||
*/
|
||
export async function GET(request: NextRequest, ctx: RouteContext<"/api/files/[id]">) {
|
||
const user = await getCurrentUser();
|
||
if (!user) return new Response(null, { status: 401 });
|
||
const { id } = await ctx.params;
|
||
const params = request.nextUrl.searchParams;
|
||
const file = await readAttachmentForUser(
|
||
user.id,
|
||
id,
|
||
params.get("v") === "thumb" ? "thumb" : "full",
|
||
);
|
||
if (!file) return new Response(null, { status: 404 });
|
||
|
||
const disposition = params.get("indir") === "1" ? "attachment" : "inline";
|
||
const fallbackName = file.mimeType === "application/pdf" ? "belge.pdf" : "gorsel.webp";
|
||
const name = toServedName(file.name || fallbackName, file.mimeType);
|
||
return new Response(new Uint8Array(file.bytes), {
|
||
headers: {
|
||
"Content-Type": file.mimeType,
|
||
"Content-Length": String(file.bytes.length),
|
||
"Content-Disposition": `${disposition}; filename="${asciiName(name)}"; filename*=UTF-8''${encodeURIComponent(name)}`,
|
||
// Yalnızca kullanıcının tarayıcısında; paylaşılan önbelleklere girmez.
|
||
"Cache-Control": "private, max-age=3600",
|
||
"X-Content-Type-Options": "nosniff",
|
||
},
|
||
});
|
||
}
|
||
|
||
/** Görseller WebP'ye çevrildiği için indirilen adın uzantısı içerikle uyumlu olsun. */
|
||
function toServedName(name: string, mimeType: string): string {
|
||
const ext = mimeType === "application/pdf" ? ".pdf" : ".webp";
|
||
return name.replace(/\.[a-z0-9]{1,5}$/i, "") + ext;
|
||
}
|
||
|
||
function asciiName(name: string): string {
|
||
return (
|
||
name
|
||
.normalize("NFKD")
|
||
.replace(/[^\x20-\x7e]/g, "")
|
||
.replace(/["\\]/g, "") || "dosya"
|
||
);
|
||
}
|