Updated files path to dynamically load new files.

This commit is contained in:
2026-06-21 17:00:01 +02:00 Verified
parent ead6b5a9f7
commit db6303e206
14 changed files with 77 additions and 36 deletions
+8 -4
View File
@@ -1,10 +1,14 @@
// app/actions/files.ts
'use server';
import crypto from 'crypto';
import fs from 'fs';
import fsPromises from 'fs/promises';
import path from 'path';
import crypto from 'crypto';
const isProd = process.env.NODE_ENV === "production";
const DATA_DIR = isProd ? "/app/data" : path.join(process.cwd(), "app/data");
const FILES_DIR = path.join(DATA_DIR, "files");
const generateFileHash = (filePath: string): Promise<string> => {
return new Promise((resolve, reject) => {
@@ -19,15 +23,15 @@ const generateFileHash = (filePath: string): Promise<string> => {
export async function getLocalFileMeta(fileUrl: string) {
try {
const cleanPath = fileUrl.startsWith('/') ? fileUrl.substring(1) : fileUrl;
const fullPath = path.join(process.cwd(), 'public', cleanPath);
const cleanName = decodeURIComponent(fileUrl.split('/').pop() || '');
const fullPath = path.join(FILES_DIR, cleanName);
const stats = await fsPromises.stat(fullPath);
const sizeMb = (stats.size / (1024 * 1024)).toFixed(2) + ' MB';
const fileHash = await generateFileHash(fullPath);
return { size: sizeMb, version: fileHash };
} catch (error) {
console.error(`Kunde inte läsa filen: ${fileUrl}`, error);
console.error(`Kunde inte läsa filen (actions): ${fileUrl}`, error);
return { size: "Okänd", version: "v1" };
}
}
+20 -6
View File
@@ -3,32 +3,42 @@
{
"title": "Turistkarta",
"icon": "Map",
"file": "/files/Turistkarta - Kullaberg.pdf"
"file": "Turistkarta - Kullaberg.pdf"
},
{
"title": "Orienteringskarta",
"icon": "MapPlus",
"file": "/files/Orienteringskarta - Kullaberg.pdf"
"file": "Orienteringskarta - Kullaberg.pdf"
},
{
"title": "Badplatser att besöka",
"icon": "WavesLadder",
"file": "/files/Badplatser på Kullaberg.pdf"
"file": "Badplatser på Kullaberg.pdf"
},
{
"title": "Vandringsrutter",
"icon": "MapPinned",
"file": "/files/Vandringsrutter.pdf"
"file": "Vandringsrutter.pdf"
},
{
"title": "Underlag för guidediplomering",
"icon": "BookCopy",
"file": "/files/Underlag för guidediplomering.pdf"
"file": "Underlag för guidediplomering.pdf"
},
{
"title": "Destinationskunskap Kullahalvön",
"icon": "BookCopy",
"file": "/files/Destinationskunskap.pdf"
"file": "Destinationskunskap.pdf"
},
{
"title": "Tjänstgöringsrapport",
"icon": "BookCopy",
"file": "Tjänstgöringsrapport 2026.pdf"
},
{
"title": "Information om ditt sommarjobb",
"icon": "BookCopy",
"file": "Information om ditt sommarjobb 2026.pdf"
}
],
"links": [
@@ -48,6 +58,10 @@
"title": "Skåneleden",
"url": "https://www.skaneleden.se/en"
},
{
"title": "RSNV Brandriskprognos",
"url": "https://rsnv.se/brandriskprognos/"
},
{
"title": "Väderprognos Mölle",
"url": "https://www.smhi.se/vader/prognoser-och-varningar/vaderprognos/q/H%C3%B6gan%C3%A4s/M%C3%B6lle/2691501"
Binary file not shown.
+2 -22
View File
@@ -19,27 +19,6 @@ const IconMap: Record<string, any> = {
"FileText": FileText
};
const fetchFileMeta = async (url: string) => {
try {
const res = await fetch(url, { method: 'HEAD', cache: 'no-store' });
const bytes = res.headers.get('content-length');
const lastModified = res.headers.get('last-modified');
const etag = res.headers.get('etag');
let sizeStr = "Okänd";
if (bytes) {
const mb = (parseInt(bytes) / (1024 * 1024)).toFixed(2);
sizeStr = `${mb} MB`;
}
const version = etag ? etag.replace(/"/g, '') :
(lastModified ? new Date(lastModified).getTime().toString() : 'v1');
return { size: sizeStr, version };
} catch (error) {
return { size: "Okänd", version: "v1" };
}
};
export default function Documents() {
const [isHydrated, setIsHydrated] = useState(false);
const [isOffline, setIsOffline] = useState(false);
@@ -73,7 +52,8 @@ export default function Documents() {
const docsWithMeta = await Promise.all(
(res.data.docs || []).map(async (doc: DocumentItem) => {
const meta = await getLocalFileMeta(doc.file);
const versionedUrl = `${doc.file}?v=${meta.version}`;
const fileNameOnly = doc.file.split('/').pop();
const versionedUrl = `/files/${fileNameOnly}?v=${meta.version}`;
return {
...doc,
+42
View File
@@ -0,0 +1,42 @@
// app/files/[...slug]/route.ts
import fs from 'fs';
import { NextRequest, NextResponse } from 'next/server';
import path from 'path';
const isProd = process.env.NODE_ENV === "production";
const DATA_DIR = isProd ? "/app/data" : path.join(process.cwd(), "app/data");
const FILES_DIR = path.join(DATA_DIR, "files");
export async function GET(
request: NextRequest,
{ params }: { params: Promise<{ slug: string[] }> }
) {
try {
const resolvedParams = await params;
const filename = decodeURIComponent(resolvedParams.slug[resolvedParams.slug.length - 1]);
const filePath = path.join(FILES_DIR, filename);
if (!fs.existsSync(filePath)) {
console.error(`404 - Filen finns inte på disk: ${filePath}`);
return new NextResponse('Filen hittades inte', { status: 404 });
}
const fileBuffer = fs.readFileSync(filePath);
let contentType = 'application/pdf';
if (filename.toLowerCase().endsWith('.png')) contentType = 'image/png';
else if (filename.toLowerCase().endsWith('.jpg') || filename.toLowerCase().endsWith('.jpeg')) contentType = 'image/jpeg';
else if (filename.toLowerCase().endsWith('.doc') || filename.toLowerCase().endsWith('.docx')) contentType = 'application/msword';
return new NextResponse(fileBuffer, {
headers: {
'Content-Type': contentType,
'Content-Disposition': `inline; filename="${filename}"`
},
});
} catch (error) {
console.error("Fel vid fildelning:", error);
return new NextResponse('Ett internt serverfel uppstod', { status: 500 });
}
}
+1
View File
@@ -23,6 +23,7 @@ const nextConfig: NextConfig = {
output: "standalone",
allowedDevOrigins: [
'10.10.0.121',
'10.11.0.122',
'localhost',
],
};