Thursday, 6 July 2017

How do I reuse a stream?

The code below gets hung up in the uploadToS3 function because the stream has already been read by the setFileID function. I understand I could save the file and create another read stream, but I would prefer not save the file locally first. I'm guessing the solution will have something to do with pipes, but I just can't seem to wrap my head around it.import multer from 'multer' import aws from 'aws-sdk' import crypto from 'crypto' import fs from 'fs' export const s3 = new aws.S3({ accessKeyId: process.env.AWS_ACCESS_KEY_ID, secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY, region: process.env.AWS_DEFAULT_REGION, }) function filterImages(files) { return files.filter((file) => { if (/image/.exec(file.detectedMimeType)) { return true } return false }) } function filterSize(files, size) { return files.filter((file) => { if (file.size > size) { return false } return true }) } function setFileID(file) { const md5 = file.stream.pipe(crypto.createHash('md5').setEncoding('hex')) return new Promise((resolve, reject) => { md5.on('finish', () => { resolve(file) }) md5.on('error', () => { reject() }) }) } function filterS3Duplicates(files, folder) { const params = { Bucket: process.env.AWS_S3_BUCKET, Delimiter: '/', Prefix: folder, } return s3.listObjects(params).promise().then((data) => { return Promise.all(files.map(file => setFileID(file).then(newFile => newFile))).then(() => files.filter((file) => { data.Contents.forEach((object) => { if (object.ETag === file.id) { return false } return true }) return true })) }) } function uploadToS3(file, destination) { const params = { Bucket: process.env.AWS_S3_BUCKET, ACL: 'public-read', Key: destination + file.id + file.detectedFileExtension, Body: file.stream, } return new Promise((resolve, reject) => { s3.upload(params, (err, data) => { if (err) reject(err) resolve(data) }) }) } export function parseBody(req, res, next) { const upload = multer() switch (req.params.formName) { case 'questionnaire': req.uploadDestination = `users/${req.user.id}/forms/${req.params.formName}/uploads/` return upload.array('accidentPhotos')(req, res, next) default: return upload.none()(req, res, next) } } export default (req, res, next) => { req.files = filterImages(req.files) req.files = filterSize(req.files, 1.0e7) Promise.all(req.files.map((file) => { return setFileID(file) })).then((files) => { return filterS3Duplicates(files, req.uploadDestination) }).then((files) => { return Promise.all(files.map((file) => { return uploadToS3(file, req.uploadDestination) })) }).then((response) => { res.locals.location = [] response.forEach((data) => { res.locals.location.push(data.Location) }) next() }) }

Submitted July 06, 2017 at 10:21PM by Never-Uses-Sarcasm

No comments:

Post a Comment