Spaces:
Running
Running
const express = require('express'); | |
const fs = require('fs'); | |
const path = require('path'); | |
const multer = require('multer'); | |
const app = express(); | |
const uploadDir = path.join(__dirname, 'uploads'); | |
// Ensure uploads directory exists | |
if (!fs.existsSync(uploadDir)) { | |
fs.mkdirSync(uploadDir); | |
} | |
// Function to generate a short random ID (alphanumeric) | |
function generateShortId() { | |
return Math.random().toString(36).substring(2, 7); // Generates a random string of length 5 | |
} | |
// Configure multer for file storage | |
const storage = multer.diskStorage({ | |
destination: function (req, file, cb) { | |
cb(null, uploadDir); | |
}, | |
filename: function (req, file, cb) { | |
const shortId = generateShortId(); | |
cb(null, `${shortId}-${file.originalname}`); | |
} | |
}); | |
const upload = multer({ storage: storage }); | |
// Route for browser upload | |
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>Enhanced File Upload</title> | |
<style> | |
body { | |
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; | |
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); | |
height: 100vh; | |
margin: 0; | |
display: flex; | |
justify-content: center; | |
align-items: center; | |
} | |
.container { | |
background-color: rgba(255, 255, 255, 0.9); | |
padding: 2rem; | |
border-radius: 10px; | |
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); | |
text-align: center; | |
width: 300px; | |
} | |
h1 { | |
color: #4a5568; | |
margin-bottom: 1.5rem; | |
} | |
form { | |
display: flex; | |
flex-direction: column; | |
align-items: center; | |
} | |
input[type="file"] { | |
display: none; | |
} | |
.file-label { | |
background-color: #4a5568; | |
color: white; | |
padding: 0.5rem 1rem; | |
border-radius: 5px; | |
cursor: pointer; | |
margin-bottom: 1rem; | |
transition: background-color 0.3s ease; | |
} | |
.file-label:hover { | |
background-color: #2d3748; | |
} | |
#file-name { | |
margin-bottom: 1rem; | |
word-break: break-all; | |
} | |
button { | |
background-color: #4299e1; | |
color: white; | |
border: none; | |
padding: 0.5rem 1rem; | |
border-radius: 5px; | |
cursor: pointer; | |
transition: background-color 0.3s ease; | |
} | |
button:hover { | |
background-color: #3182ce; | |
} | |
#upload-progress { | |
width: 100%; | |
background-color: #e2e8f0; | |
border-radius: 5px; | |
margin-top: 1rem; | |
overflow: hidden; | |
display: none; | |
} | |
#progress-bar { | |
width: 0; | |
height: 10px; | |
background-color: #48bb78; | |
transition: width 0.5s ease; | |
} | |
</style> | |
</head> | |
<body> | |
<div class="container"> | |
<h1>Upload File</h1> | |
<form id="upload-form" action="/upload" method="post" enctype="multipart/form-data"> | |
<label for="file-upload" class="file-label">Choose File</label> | |
<input id="file-upload" type="file" name="file"> | |
<div id="file-name"></div> | |
<button type="submit">Upload</button> | |
</form> | |
<div id="upload-progress"> | |
<div id="progress-bar"></div> | |
</div> | |
</div> | |
<script> | |
const fileUpload = document.getElementById('file-upload'); | |
const fileName = document.getElementById('file-name'); | |
const uploadForm = document.getElementById('upload-form'); | |
const uploadProgress = document.getElementById('upload-progress'); | |
const progressBar = document.getElementById('progress-bar'); | |
fileUpload.addEventListener('change', (e) => { | |
if (e.target.files.length > 0) { | |
fileName.textContent = e.target.files[0].name; | |
} else { | |
fileName.textContent = ''; | |
} | |
}); | |
uploadForm.addEventListener('submit', (e) => { | |
e.preventDefault(); | |
if (!fileUpload.files.length) { | |
alert('Please select a file to upload.'); | |
return; | |
} | |
const formData = new FormData(uploadForm); | |
const xhr = new XMLHttpRequest(); | |
xhr.open('POST', '/upload', true); | |
xhr.upload.onprogress = (event) => { | |
if (event.lengthComputable) { | |
const percentComplete = (event.loaded / event.total) * 100; | |
uploadProgress.style.display = 'block'; | |
progressBar.style.width = percentComplete + '%'; | |
} | |
}; | |
xhr.onload = function() { | |
if (xhr.status === 200) { | |
alert('Upload complete!'); | |
document.body.innerHTML = xhr.responseText; | |
} else { | |
alert('Upload failed. Please try again.'); | |
} | |
uploadProgress.style.display = 'none'; | |
progressBar.style.width = '0'; | |
fileName.textContent = ''; | |
uploadForm.reset(); | |
}; | |
xhr.send(formData); | |
}); | |
</script> | |
</body> | |
</html> | |
`); | |
}); | |
// Handler for browser upload | |
app.post('/upload', upload.single('file'), (req, res) => { | |
if (!req.file) { | |
return res.status(400).send('No file uploaded.'); | |
} | |
const fileUrl = `https://zhofang-temp-storage.hf.space/${req.file.filename.split('-')[0]}/${req.file.originalname}`; | |
res.send(` | |
<html> | |
<head> | |
<title>File Uploaded</title> | |
<style> | |
body { | |
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; | |
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); | |
height: 100vh; | |
margin: 0; | |
display: flex; | |
justify-content: center; | |
align-items: center; | |
color: white; | |
} | |
.container { | |
background-color: rgba(255, 255, 255, 0.1); | |
padding: 2rem; | |
border-radius: 10px; | |
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); | |
text-align: center; | |
} | |
a { | |
color: #4299e1; | |
text-decoration: none; | |
} | |
a:hover { | |
text-decoration: underline; | |
} | |
</style> | |
</head> | |
<body> | |
<div class="container"> | |
<h1>File Uploaded Successfully</h1> | |
<p>Uploaded 1 file, ${req.file.size} bytes</p> | |
<p>Download link: <a href="${fileUrl}">${fileUrl}</a></p> | |
<p>wget command: <code>wget ${fileUrl}</code></p> | |
</div> | |
</body> | |
</html> | |
`); | |
// Delete file after 24 hours | |
setTimeout(() => { | |
fs.unlink(req.file.path, (err) => { | |
if (err) console.error(`Error deleting file: ${err}`); | |
}); | |
}, 24 * 60 * 60 * 1000); // 24 hours in milliseconds | |
}); | |
// Route for upload via PUT (like bashupload) | |
app.put('/:filename', (req, res) => { | |
const shortId = generateShortId(); | |
const filename = req.params.filename; | |
const filepath = path.join(uploadDir, `${shortId}-${filename}`); | |
const fileStream = fs.createWriteStream(filepath); | |
req.pipe(fileStream); | |
fileStream.on('finish', () => { | |
const fileUrl = `https://zhofang-temp-storage.hf.space/${shortId}/${filename}`; | |
res.send(`Uploaded 1 file, ${req.headers['content-length']} bytes\n\nwget ${fileUrl}\n`); | |
// Delete file after 24 hours | |
setTimeout(() => { | |
fs.unlink(filepath, (err) => { | |
if (err) console.error(`Error deleting file: ${err}`); | |
}); | |
}, 24 * 60 * 60 * 1000); // 24 hours in milliseconds | |
}); | |
fileStream.on('error', (err) => { | |
console.error(`Error writing file: ${err}`); | |
res.status(500).send('Error uploading file.'); | |
}); | |
}); | |
app.get('/:id/:filename', (req, res) => { | |
const filepath = path.join(uploadDir, `${req.params.id}-${req.params.filename}`); | |
res.download(filepath, req.params.filename, (err) => { | |
if (err) { | |
console.error(`Error downloading file: ${err}`); | |
res.status(404).send('File not found.'); | |
} | |
}); | |
}); | |
app.listen(7860, () => { | |
console.log('Server is running on http://localhost:3000'); | |
}); |