Repository navigation
Expand file tree
/
Copy pathserver.js
More file actions
162 lines (140 loc) · 5.35 KB
/
Copy pathserver.js
File metadata and controls
162 lines (140 loc) · 5.35 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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
const express = require('express');
const cors = require('cors');
const multer = require('multer');
const path = require('path');
const fs = require('fs');
const { v4: uuidv4 } = require('uuid');
const open = require('open');
const sharp = require('sharp'); // Keep sharp for other potential uses
const PlaywrightRenderer = require('./renderer');
// Setup temp directory
const tempDir = path.join(__dirname, 'temp');
if (!fs.existsSync(tempDir)) {
fs.mkdirSync(tempDir);
}
// Configure multer for file uploads
const storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, tempDir);
},
filename: function (req, file, cb) {
cb(null, uuidv4() + path.extname(file.originalname));
}
});
const upload = multer({ storage: storage });
const app = express();
const PORT = process.env.PORT || 3015;
// Middleware
app.use(cors());
app.use(express.json({ limit: '50mb' }));
app.use(express.urlencoded({ extended: true, limit: '50mb' }));
app.use('/temp', express.static(tempDir));
app.use(express.static(__dirname));
// Cleanup task
// Cleanup uploaded files only (since output is now in-memory)
function cleanupTempFiles() {
fs.readdir(tempDir, (err, files) => {
if (err) return console.error('Error cleaning temp files:', err);
const now = Date.now();
const oneHourAgo = now - 3600000;
files.forEach(file => {
const filePath = path.join(tempDir, file);
fs.stat(filePath, (err, stats) => {
if (err) return;
if (stats.mtimeMs < oneHourAgo) {
fs.unlink(filePath, () => { });
}
});
});
});
}
setInterval(cleanupTempFiles, 3600000);
// Initialize Renderer
const renderer = new PlaywrightRenderer();
// Routes
app.post('/convert/url', async (req, res) => {
const { url, settings } = req.body;
console.log('📨 [Server] Received /convert/url request');
const { format, scale, smartCrop, smartCropPadding, width, dynamicMode, watermarkEnabled, watermarkText } = settings || {};
if (!url) return res.status(400).json({ error: 'URL is required' });
try {
const buffer = await renderer.capture({
input: url,
inputType: 'url',
format: format || 'png',
scale: Number(scale) || 2,
smartCrop: !!smartCrop,
smartCropPadding: smartCropPadding !== undefined ? Number(smartCropPadding) : 0,
viewportWidth: Number(width) || 1200,
dynamicMode: !!dynamicMode,
watermarkEnabled: !!watermarkEnabled,
watermarkText: watermarkText || ''
});
res.set('Content-Type', `image/${format || 'png'}`);
res.send(buffer);
} catch (error) {
console.error('API Error:', error);
res.status(500).json({ error: error.message });
}
});
app.post('/convert/html', async (req, res) => {
const { html, settings } = req.body;
const { format, scale, smartCrop, smartCropPadding, width, dynamicMode, watermarkEnabled, watermarkText } = settings || {};
if (!html) return res.status(400).json({ error: 'HTML content is required' });
try {
const buffer = await renderer.capture({
input: html,
inputType: 'html',
format: format || 'png',
scale: Number(scale) || 2,
smartCrop: !!smartCrop,
smartCropPadding: smartCropPadding !== undefined ? Number(smartCropPadding) : 0,
viewportWidth: Number(width) || 1200,
dynamicMode: !!dynamicMode,
watermarkEnabled: !!watermarkEnabled,
watermarkText: watermarkText || ''
});
res.set('Content-Type', `image/${format || 'png'}`);
res.send(buffer);
} catch (error) {
console.error('API Error:', error);
res.status(500).json({ error: error.message });
}
});
app.post('/convert/file', upload.single('htmlFile'), async (req, res) => {
if (!req.file) return res.status(400).json({ error: 'HTML file is required' });
try {
const settings = req.body.settings ? JSON.parse(req.body.settings) : {};
const { format, scale, smartCrop, smartCropPadding, width, dynamicMode, watermarkEnabled, watermarkText } = settings;
const filePath = req.file.path;
const buffer = await renderer.capture({
input: filePath,
inputType: 'file',
format: format || 'png',
scale: Number(scale) || 2,
smartCrop: !!smartCrop,
smartCropPadding: smartCropPadding !== undefined ? Number(smartCropPadding) : 0,
viewportWidth: Number(width) || 1200,
dynamicMode: !!dynamicMode,
watermarkEnabled: !!watermarkEnabled,
watermarkText: watermarkText || ''
});
// Cleanup uploaded file
fs.unlinkSync(filePath);
res.set('Content-Type', `image/${format || 'png'}`);
res.send(buffer);
} catch (error) {
console.error('API Error:', error);
res.status(500).json({ error: error.message });
}
});
// Start server
app.listen(PORT, async () => {
console.log(`🚀 Server running at http://localhost:${PORT}`);
// Initialize browser immediately
await renderer.init();
console.log('Opening browser...');
setTimeout(() => {
open(`http://localhost:${PORT}/index.html`);
}, 1000);
});