-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathserver.ts
More file actions
117 lines (96 loc) · 3.68 KB
/
server.ts
File metadata and controls
117 lines (96 loc) · 3.68 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
import express from 'express';
import path from 'path';
import { fileURLToPath } from 'url';
import fs from 'fs';
import cors from 'cors';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const app = express();
const port = process.env.PORT || 3000;
// Enable CORS for API calls
app.use(cors());
app.use(express.json());
// Serve static files from dist directory
app.use(express.static(path.join(__dirname, 'dist')));
// Data directory path (one level up from PathAnalysis)
const dataDirectory = path.resolve(__dirname, '../Data');
// API endpoint to list available CSV files
app.get('/api/data-files', (_req, res) => {
try {
if (!fs.existsSync(dataDirectory)) {
return res.json({ files: [], error: 'Data directory not found' });
}
const files = fs.readdirSync(dataDirectory)
.filter(file => file.endsWith('.csv'))
.map(filename => {
const filePath = path.join(dataDirectory, filename);
const stats = fs.statSync(filePath);
return {
filename,
size: stats.size,
modified: stats.mtime.toISOString(),
path: `/api/data-files/${encodeURIComponent(filename)}`
};
})
.sort((a, b) => new Date(b.modified).getTime() - new Date(a.modified).getTime());
res.json({ files, dataDirectory });
} catch (error) {
console.error('Error listing data files:', error);
res.status(500).json({ error: 'Failed to list data files' });
}
});
// API endpoint to serve specific CSV files
app.get('/api/data-files/:filename', (req, res) => {
try {
const filename = decodeURIComponent(req.params.filename);
const filePath = path.join(dataDirectory, filename);
// Security check: ensure file is within data directory
if (!filePath.startsWith(dataDirectory)) {
return res.status(403).json({ error: 'Access denied' });
}
if (!fs.existsSync(filePath)) {
return res.status(404).json({ error: 'File not found' });
}
// Set appropriate headers for CSV download
res.setHeader('Content-Type', 'text/csv');
res.setHeader('Content-Disposition', `attachment; filename="${filename}"`);
// Stream the file
const fileStream = fs.createReadStream(filePath);
fileStream.pipe(res);
} catch (error) {
console.error('Error serving data file:', error);
res.status(500).json({ error: 'Failed to serve file' });
}
});
// API endpoint to get CSV file content as text
app.get('/api/data-files/:filename/content', (req, res) => {
try {
const filename = decodeURIComponent(req.params.filename);
const filePath = path.join(dataDirectory, filename);
// Security check: ensure file is within data directory
if (!filePath.startsWith(dataDirectory)) {
return res.status(403).json({ error: 'Access denied' });
}
if (!fs.existsSync(filePath)) {
return res.status(404).json({ error: 'File not found' });
}
const content = fs.readFileSync(filePath, 'utf-8');
res.setHeader('Content-Type', 'text/plain');
res.send(content);
} catch (error) {
console.error('Error reading data file:', error);
res.status(500).json({ error: 'Failed to read file' });
}
});
// Catch all handler for React app
app.get('*', (_req, res) => {
res.sendFile(path.resolve(__dirname, 'dist', 'index.html'));
});
app.listen(port, () => {
console.log(`Server is running on port ${port}`);
console.log(`Data directory: ${dataDirectory}`);
console.log(`API endpoints:`);
console.log(` - GET /api/data-files (list CSV files)`);
console.log(` - GET /api/data-files/:filename (download CSV)`);
console.log(` - GET /api/data-files/:filename/content (get CSV content)`);
});