piczip / canvas.js
nagose's picture
Update canvas.js
34a132c verified
raw
history blame
4.08 kB
const express = require('express');
const multer = require('multer');
const JSZip = require('jszip');
const { createCanvas } = require('canvas');
const crypto = require('crypto');
const app = express();
// 设置 multer 用于处理文件上传
const storage = multer.memoryStorage();
const upload = multer({ storage: storage });
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
// 新增 GET / 路由来提供前端页面
app.get('/', (req, res) => {
res.send(`
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>File Upload</title>
</head>
<body>
<h1>Upload a File</h1>
<form id="uploadForm" action="/upload" method="post" enctype="multipart/form-data">
<input type="file" id="fileInput" name="file" required>
<button type="submit">Upload</button>
</form>
<script>
document.getElementById('uploadForm').addEventListener('submit', async (event) => {
event.preventDefault();
const formData = new FormData(event.target);
const response = await fetch(event.target.action, {
method: 'POST',
body: formData
});
if (response.ok) {
response.blob().then(blob => {
const url = window.URL.createObjectURL(blob);
const a = document.createElement('a');
a.style.display = 'none';
a.href = url;
// 从Content-Disposition头中提取文件名
const contentDisposition = response.headers.get('Content-Disposition');
const fileName = contentDisposition.match(/filename="(.+)"/)[1];
a.download = fileName;
document.body.appendChild(a);
a.click();
window.URL.revokeObjectURL(url);
alert('File downloaded successfully!');
});
} else {
alert('Failed to upload file.');
}
});
</script>
</body>
</html>
`);
});
app.post('/upload', upload.single('file'), async (req, res) => {
try {
const file = req.file;
const fileName = file.originalname;
const fileType = file.mimetype;
const fileBuffer = file.buffer;
// 压缩文件成 zip 格式
const zip = new JSZip();
zip.file(fileName, fileBuffer);
const zipBuffer = await zip.generateAsync({ type: 'nodebuffer' });
// 创建包含文件信息的表格图片
const width = 400;
const height = 300;
const canvas = createCanvas(width, height);
const ctx = canvas.getContext('2d');
ctx.fillStyle = '#FFFFFF';
ctx.fillRect(0, 0, width, height);
ctx.fillStyle = '#000000';
ctx.font = '20px WenQuanYi Zen Hei';
const text = `
File Name: ${fileName}
File Type: ${fileType}
File Size: ${fileBuffer.length} bytes
Created At: ${new Date().toLocaleString()}
`;
ctx.fillText(text.trim(), 10, 100);
const rawImageData = canvas.toBuffer('image/jpeg', { quality: 0.75 });
const finalBuffer = Buffer.concat([rawImageData, zipBuffer]);
//const outputFileName = encodeURIComponent(fileName.replace(/\.[^/.]+$/, "") + '-pic.zip.jpg');
// 生成随机的哈希值作为文件名
const hash = crypto.randomBytes(16).toString('hex');
const outputFileName = encodeURIComponent(hash + '-pic.zip.jpg');
res.setHeader('Content-Type', 'image/jpeg');
res.setHeader('Content-Disposition', `attachment; filename="${outputFileName}"`);
res.send(finalBuffer);
} catch (error) {
console.error(error);
res.status(500).send('An error occurred');
}
});
const PORT = process.env.PORT || 7860;
app.listen(PORT, () => {
console.log(`Server running on port ${PORT}`);
});