diff --git a/app/helpers/fs.js b/app/helpers/fs.js index cda9527..2d042f6 100644 --- a/app/helpers/fs.js +++ b/app/helpers/fs.js @@ -1,9 +1,6 @@ const path = require('path'); const fs = require('fs'); -const fsPromises = require('fs').promises; -const mime = require("mime"); - -const { access, readdir, copyFile, readFile, writeFile, mkdir, rename, unlink } = fsPromises; +const { access, readdir, copyFile, readFile, writeFile, mkdir, rename, unlink } = fs.promises; const config = require('./config.js'); @@ -12,16 +9,16 @@ let FS = module.exports = {}; FS.ROOT = config('directories')['root']; class FSError extends Error { - constructor(error) { - super(error); + constructor() { + super(); Error.captureStackTrace(this, this.constructor); this.name = "FSError"; } } class FSAccessError extends FSError { - constructor(error) { - super(error); + constructor() { + super(); this.name = "FSAccessError"; } } @@ -190,10 +187,6 @@ FS.renameFile = async (old, mew, rootType) => { } }; -FS.getMime = async filePath => await mime.getType(filePath); - -FS.getExtension = async filePath => await mime.getExtension(filePath); - async function createDirectoryIfNotExists(directory, rootType) { directory = FS.normalize(directory, rootType); checkAndThrow(directory); diff --git a/app/routes/http/parse.js b/app/routes/http/parse.js index 3ed0057..903e3b4 100644 --- a/app/routes/http/parse.js +++ b/app/routes/http/parse.js @@ -1,4 +1,6 @@ const Busboy = require('busboy'); +const FileType = require('file-type'); + const path = require('path'); const config = require('../../helpers/config'); const FS = require('../../helpers/fs'); @@ -43,38 +45,39 @@ module.exports = ctx => { return new Promise((resolve, reject) => { let busboy = new Busboy({ headers: ctx.req.headers }); let fields = {}; + let uploadedFiles = []; ctx.req.pipe(busboy); - setTimeout(() => resolve('Body parsing timeout'), 5000); + setTimeout(() => reject('Body parsing timeout'), 5000); - busboy.on('file', async (fieldname, file, filename, encoding) => { + busboy.on('file', async (fieldname, file, filename) => { + let size = 0; + let {ext, mime} = await FileType.fromStream(file); - if (!filename) { //TODO: Filter mimetype - return file.resume(); + if (!(fieldname.startsWith('file'))) { + throw new Error('Files must be in appropriate form fields'); + } + if (!mime) { + throw new Error('Unsupported file type: ' + filename); } - let extension = path.parse(filename).ext; - let tmpPath = path.join(config('directories.temporary'), +new Date + extension); - - setTimeout(async () => { - await FS.unlink(tmpPath); - }, 300000); - + let tmpPath = path.join(config('directories.temporary'), +new Date + '.' + ext); - let size = 0; + uploadedFiles.push(tmpPath); file.on('data', data => size += data.length); - file.pipe(FS.createWriteStream(tmpPath)).on('close', async () => { + file.on('end', async () => { correctFieldMatching(fields, fieldname, { - encoding, - mime: await FS.getMime(tmpPath), - extension: await FS.getExtension(tmpPath) || extension, + mime, + extension: ext, name: filename, size, path: tmpPath }); }); + + file.pipe(FS.createWriteStream(tmpPath)); }); busboy.on('field', (fieldname, val) => correctFieldMatching(fields, fieldname, val)); @@ -85,8 +88,12 @@ module.exports = ctx => { ctx.request.body = fields; } resolve(ctx.request.body); + uploadedFiles.forEach(file => FS.unlink(file)); // TODO: Remove this and call after move/copy }); - busboy.on('error', reject); + busboy.on('error', err => { + reject(err); + uploadedFiles.forEach(file => FS.unlink(file)); + }); }); }; diff --git a/package.json b/package.json index 45c5ef3..eb59304 100644 --- a/package.json +++ b/package.json @@ -22,12 +22,11 @@ "crc": "^3.8.0", "dot": "^1.1.3", "figurecon": "github:rngnrs/figurecon", + "file-type": "^14.6.2", "ioredis": "^3.2.2", "jwt-simple": "^0.5.6", "koa": "^2.11.0", "koa-router": "^7.2.1", - "mime": "^2.4.4", - "mmmagic": "^0.5.3", "sharp": "^0.23.4", "ws": "^3.1.0" },