mirror of
https://github.com/chatmail/core.git
synced 2026-04-19 14:36:29 +03:00
- This adds params for the upload URL and local file path, so that the actual upload can happen in the send job. - This also moves the URL generation to the client side so that we can generate a valid URL before the upload (because the MIME rendering of the mail message happens earlier and we want to include the URL there)
74 lines
2.2 KiB
JavaScript
74 lines
2.2 KiB
JavaScript
const p = require('path')
|
|
const express = require('express')
|
|
const fs = require('fs')
|
|
const { pipeline } = require('stream')
|
|
|
|
const app = express()
|
|
|
|
const config = {
|
|
path: process.env.UPLOAD_PATH || p.resolve('./uploads'),
|
|
port: process.env.PORT || 8080,
|
|
hostname: process.env.HOSTNAME || '0.0.0.0',
|
|
baseurl: process.env.BASE_URL
|
|
}
|
|
|
|
if (!config.baseurl) config.baseurl = `http://${config.hostname}:${config.port}/`
|
|
if (!config.baseurl.endsWith('/')) config.baseurl = config.baseurl + '/'
|
|
|
|
if (!fs.existsSync(config.path)) {
|
|
fs.mkdirSync(config.path, { recursive: true })
|
|
}
|
|
|
|
app.use('/:filename', checkFilenameMiddleware)
|
|
app.put('/:filename', (req, res) => {
|
|
const uploadpath = req.uploadpath
|
|
const filename = req.params.filename
|
|
fs.stat(uploadpath, (err, stat) => {
|
|
if (err && err.code !== 'ENOENT') {
|
|
console.error('error', err.message)
|
|
return res.code(500).send('internal server error')
|
|
}
|
|
if (stat) return res.status(500).send('filename in use')
|
|
|
|
const ws = fs.createWriteStream(uploadpath)
|
|
pipeline(req, ws, err => {
|
|
if (err) {
|
|
console.error('error', err.message)
|
|
return res.status(500).send('internal server error')
|
|
}
|
|
console.log('file uploaded: ' + uploadpath)
|
|
const url = config.baseurl + filename
|
|
res.end(url)
|
|
})
|
|
})
|
|
})
|
|
|
|
app.get('/:filename', (req, res) => {
|
|
const uploadpath = req.uploadpath
|
|
const rs = fs.createReadStream(uploadpath)
|
|
res.setHeader('content-type', 'application/octet-stream')
|
|
pipeline(rs, res, err => {
|
|
if (err) console.error('error', err.message)
|
|
if (err) return res.status(500).send(err.message)
|
|
})
|
|
})
|
|
|
|
function checkFilenameMiddleware (req, res, next) {
|
|
const filename = req.params.filename
|
|
if (!filename) return res.status(500).send('missing filename')
|
|
if (!filename.match(/^[a-zA-Z0-9]{26,32}$/)) {
|
|
return res.status(500).send('illegal filename')
|
|
}
|
|
const uploadpath = p.normalize(p.join(config.path, req.params.filename))
|
|
if (!uploadpath.startsWith(config.path)) {
|
|
return res.code(500).send('bad request')
|
|
}
|
|
req.uploadpath = uploadpath
|
|
next()
|
|
}
|
|
|
|
app.listen(config.port, err => {
|
|
if (err) console.error(err)
|
|
else console.log(`Listening on ${config.baseurl}`)
|
|
})
|