Created
August 15, 2020 02:02
-
-
Save 58bits/44d6463f3df6d652601c74e63736b693 to your computer and use it in GitHub Desktop.
MultiPart Handler
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'use strict' | |
const config = require('../../config') | |
const { MultipartError } = require('./errors') | |
const fs = require('fs') | |
const path = require('path') | |
const nanoid = require('nanoid') | |
const Multipart = (request, response, done) => { | |
// Note: onFile and addToBody cannot be handled on a per reuqest basis at the moment | |
// https://github.com/fastify/fastify-multipart/issues/129 | |
// https://github.com/fastify/fastify-multipart/issues/131#issuecomment-649345687 | |
if (!request.isMultipart()) { | |
return response.code(400).header('Connection', 'close').send(new MultipartError('Request is not multipart')) | |
} | |
const fields = {} | |
const files = {} | |
const mp = request.multipart(() => { }, () => { }, { | |
limits: { | |
fileSize: 1024 * 1024 * 8, | |
files: 10 }, | |
allowed: ['image/jpeg', 'image/jpg', 'image/png', 'image/gif', 'image/webp', 'video/mp4', 'video/webm', 'text/html'], | |
}) | |
mp.on('field', (fieldname, value) => { | |
fields[fieldname] = value | |
}) | |
mp.on('file', (fieldname, file, filename, encoding, mimetype) => { | |
if (!filename || filename == '') { | |
file.destroy(new Error('No file provided')) | |
} else if (!mp.opts.allowed.includes(mimetype)) { | |
file.destroy(new Error('Not allowed file type')) | |
} else { | |
// Generate new filename | |
filename = nanoid.customAlphabet('0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz', 11)() + path.extname(filename) | |
// Add file to local list | |
files[fieldname] = files[fieldname] || [] | |
files[fieldname].push({ | |
filename: filename, | |
mimetype: mimetype, | |
extension: path.extname(filename).substring(1), | |
}) | |
// Write stream to local file | |
let destination = path.join(config.storage.temp, filename) | |
var ffs = fs.createWriteStream(destination) | |
file.pipe(ffs) | |
} | |
file.on('limit', () => { | |
file.destroy(new Error('File size limit reached')) | |
}) | |
file.on('error', (error) => { | |
mp.destroy(error) | |
}) | |
}) | |
mp.on('partsLimit', () => { | |
mp.destroy(new Error('Maximum number of form parts reached')) | |
}) | |
mp.on('filesLimit', () => { | |
mp.destroy(new Error('Maximum number of files reached')) | |
}) | |
mp.on('fieldsLimit', () => { | |
mp.destroy(new Error('Maximim number of fields reached')) | |
}) | |
mp.on('error', (error) => { | |
for (let i in files) { | |
for (let j in files[i]) { | |
let source = path.join(config.storage.temp, files[i][j].filename) | |
if (fs.statSync(source)) { | |
fs.unlinkSync(source) | |
} | |
} | |
} | |
/// TODO: Test - but do not THROW the error here, or Node.js will crash. | |
const appError = new MultipartError('Error in multipart file upload handler; lib/multipart', error) | |
return response.code(400).header('Connection', 'close').send(appError) | |
}) | |
mp.on('finish', () => { | |
request.body = { ...fields, ...files } | |
done() | |
}) | |
} | |
module.exports = { | |
Multipart, | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment