|
const express = require('express'); |
|
const multer = require('multer'); |
|
const JSZip = require('jszip'); |
|
const { createCanvas } = require('canvas'); |
|
const crypto = require('crypto'); |
|
const app = express(); |
|
|
|
|
|
const storage = multer.memoryStorage(); |
|
const upload = multer({ storage: storage }); |
|
|
|
app.use(express.json()); |
|
app.use(express.urlencoded({ extended: true })); |
|
|
|
|
|
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; |
|
|
|
|
|
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 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}`); |
|
}); |
|
|