filesharing/server.js

117 lines
4.5 KiB
JavaScript
Raw Normal View History

const { SERVER_HOST, SERVER_PORT, MONGODB_URL, UPLOAD_TEMP_PATH, UPLOAD_SAVE_PATH, UPLOAD_SIZE_LIMIT } = require('./config')
const fs = require('fs')
const path = require('path')
const multer = require('multer')
const bcrypt = require('bcrypt')
const md5file = require('md5-file')
2022-08-27 02:33:20 +00:00
const filesize = require('filesize')
2022-08-25 06:34:16 +00:00
const express = require('express')
const mongoose = require('mongoose')
const CronJob = require('cron').CronJob
const Filesharing = require('./models/Filesharing')
2022-08-26 04:34:04 +00:00
mongoose.connect(MONGODB_URL, (error) => {
if (error) {
console.error(error)
} else {
console.info('mongodb connected successfully')
}
})
const job = new CronJob(
'0 * * * * *',
async () => {
const files = await Filesharing.find({ createdAt: { $lt: new Date(Date.now() - 24 * 3600 * 1000) } })
for (let file of files) {
const id = file.id
await Filesharing.findByIdAndDelete(id)
console.log(`删除共享 ${id}`)
const ref_number = await Filesharing.countDocuments({ md5: file.md5 })
if (ref_number == 0) {
const file_path = path.join(__dirname, UPLOAD_SAVE_PATH, file.md5)
fs.unlinkSync(file_path)
console.log(`删除文件 ${file_path}`)
}
}
},
null,
true
)
2022-08-25 06:34:16 +00:00
const app = express()
2022-08-25 06:43:38 +00:00
app.set('view engine', 'pug')
app.use(express.static('public'))
app.use(express.urlencoded({ extended: true }))
app.use(express.json())
2022-08-27 02:33:20 +00:00
app.locals.filesize = filesize.partial({ base: 2, standard: 'jedec' })
app.locals.moment = require('moment')
app.locals.moment.locale('zh-cn')
app.get('/', async (req, res) => {
const filesharing = await Filesharing.find().sort({ createdAt: -1 })
res.render('index', { filesharing })
})
app.get('/upload', async (req, res) => {
res.render('upload')
})
const upload = multer({ dest: UPLOAD_TEMP_PATH, limits: { fileSize: UPLOAD_SIZE_LIMIT } })
app.post('/upload', upload.single('file'), async (req, res) => {
const file_temp_path = path.join(UPLOAD_TEMP_PATH, req.file.filename)
const md5 = await md5file(file_temp_path)
const file_save_path = path.join(__dirname, UPLOAD_SAVE_PATH, md5)
if (!fs.existsSync(file_save_path)) {
2022-08-26 12:50:10 +00:00
fs.cpSync(file_temp_path, file_save_path) // 复制临时文件到UPLOAD_PATH
}
fs.unlinkSync(file_temp_path) // 删除临时文件
// 写入数据库
2022-08-26 15:51:32 +00:00
const file = await Filesharing.create({
md5,
size: req.file.size,
encoding: req.file.encoding,
mimetype: req.file.mimetype,
// 解决了multer将中文文件名错误编码的问题
filename: Buffer.from(req.file.originalname, 'latin1').toString('utf8'),
password: req.body.password ? await bcrypt.hash(req.body.password, 16) : '',
})
console.log(`上传文件 ${file.filename}`)
res.status(201).render('upload', { file })
2022-08-25 06:34:16 +00:00
})
2022-08-26 16:46:04 +00:00
app.get('/download/:id', async (req, res) => {
try {
if (!req.params.id.match(/^[0-9a-fA-F]{24}$/)) throw '格式错误的ObjectId'
const file = await Filesharing.findById(req.params.id)
if (!file) throw '试图下载不存在的文件'
2022-08-26 12:46:06 +00:00
res.render('download', { file })
} catch (error) {
console.error(error)
2022-08-26 12:46:06 +00:00
res.sendStatus(404)
}
})
2022-08-26 16:46:04 +00:00
app.post('/download/:id', async (req, res) => {
try {
if (!req.params.id.match(/^[0-9a-fA-F]{24}$/)) throw '格式错误的ObjectId'
const file = await Filesharing.findById(req.params.id)
if (!file) throw '试图下载不存在的文件'
if (file.password == '' || (await bcrypt.compare(req.body.password, file.password)) == true) {
await Filesharing.findByIdAndUpdate(req.params.id, { $inc: { downloads: 1 } })
console.log(`下载文件 ${file.filename}`)
res.status(200).download(path.join(UPLOAD_SAVE_PATH, file.md5), file.filename)
2022-08-26 09:57:12 +00:00
} else {
res.sendStatus(401)
2022-08-26 09:57:12 +00:00
}
} catch (error) {
console.error(error)
2022-08-26 09:57:12 +00:00
res.sendStatus(404)
}
})
app.get('/file/:md5', async (req, res) => {
try {
const file = await Filesharing.findOne({ md5: req.params.md5 })
if (!file) throw '试图下载不存在的文件'
if (file.password != '') throw '访问的文件需要密码'
res.sendFile(path.join(__dirname, UPLOAD_SAVE_PATH, req.params.md5))
} catch (error) {
console.error(error)
res.sendStatus(404)
}
})
const server = app.listen(SERVER_PORT, SERVER_HOST, () => {
console.info(`server is running at http://${SERVER_HOST}:${SERVER_PORT}`)
2022-08-25 06:34:16 +00:00
})