Updated files path to dynamically load new files.
This commit is contained in:
1 parent
ead6b5a9f7
commit
db6303e206
13 files changed
+73
-32
No files matched your search
@@ -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
@@ -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"
|
||||
|
||||
File renamed without changes.
Binary file not shown.
Binary file not shown.
File renamed without changes.
Binary file not shown.
File renamed without changes.
File renamed without changes.
File renamed without changes.
+2
-22
@@ -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,
|
||||
|
||||
@@ -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 });
|
||||
}
|
||||
}
|
||||
@@ -23,6 +23,7 @@ const nextConfig: NextConfig = {
|
||||
output: "standalone",
|
||||
allowedDevOrigins: [
|
||||
'10.10.0.121',
|
||||
'10.11.0.122',
|
||||
'localhost',
|
||||
],
|
||||
};
|
||||
|
||||
Reference in new issue
Block a user