save image to s3 bucket with image formate - node.js

I am trying to upload an image to a s3 bucket using multerS3. It does save the file to the s3 bucket but not in an image format.
here is my code.
storage: multerS3({
s3: S3,
bucket: 'slsupload',
acl: 'public-read',
metadata: function (req, file, cb) {
cb(null, {fieldName: file.fieldname});
},
key: function (req, file, cb) {
cb(null, Date.now().toString()+".jpg")
}
})
});
const singleUpload = upload.single('file');
app.post('/test-upload', (req, res) => {
singleUpload(req, res, function(err, some) {
if (err) {
return res.status(422).send({errors: [{title: 'Image Upload Error', detail: err.message}] });
}
return res.json({'imageUrl': req.file.location});
});
});```

You can try setting the contentType buy hand or let multerS3 discover the contentType automatically:
var upload = multer({
storage: multerS3({
s3: s3,
bucket: 'some-bucket',
contentType: multerS3.AUTO_CONTENT_TYPE,
key: function (req, file, cb) {
cb(null, Date.now().toString())
}
})
})

Related

how to use sharp to resize image while uploading to s3 nodejs

I use multer to upload the images to s3. The user clicks on upload button in the frontend, and uploads the image, which is then uploaded to s3 with the helper multer backend.
But the images uploaded aren't optimised i.e if the user uploads a 4mb image, the image is uploaded with any compression. That indeed led to slow website frontend.
How do I optimise or compress the image using sharp ?
Code to upload to s3 (nodejs):
const s3 = new aws.S3({
accessKeyId: process.env.AWS_ACCESS_KEY,
secretAccessKey: process.env.AWS_SECERT_KEY,
});
//S3
const uploadS3 = multer({
storage: multerS3({
s3: s3,
bucket: "testbucket",
acl: "public-read",
metadata: function (req, file, cb) {
cb(null, { fieldName: file.fieldname });
},
key: function (req, file, cb) {
cb(null, shortid.generate() + "-" + file.originalname);
},
}),
});
router.post("/poster/create", uploadS3.array("posterPictures"), createPoster);
CreatePoster is a function that returns the path of the image in s3:
exports.createPoster = (req, res) => {
let posterPictures = [];
if (req.files.length > 0) {
posterPictures = req.files.map((file) => {
return { img: file.location };
});
}
const { name, id } = req.body;
const poster = new Poster({
name: name,
slug: slugify(name),
id,
posterPictures,
});
poster.save((error, poster) => {
if (error) return res.status(400).json(error);
if (poster) {
return res.status(201).json({ poster, files: req.files });
}
});
};

Can't upload large files to AWS with Multer S3 NodeJs

I can't upload large files to aws using multer-s3. I'm using the following code:
const upload = multer({
storage: multerS3({
s3,
bucket: 'welive-inc',
acl: 'public-read',
metadata: function (req, file, cb) {
cb(null, {fieldName: 'TESTING_META_DATA!'});
},
key: function (req, file, cb) {
cb(null, Date.now().toString() + randtoken.uid(16))
}
})
})
const singleUpload = upload.single('file');
router.post('/image-upload', (req, res) =>{
singleUpload(req, res, function(err) {
if (err) {
console.log(err)
return res.status(422).send({errors: [{title: 'File Upload Error', detail: err.message}] });
}
return res.json({'imageUrl': req.file.location});
});
});
This code works for small files (images or really small videos), but when it comes to relatively larger files it doens't work. and the console.log(err) returns this error:
{ Error: write EPIPE
at WriteWrap.onWriteComplete [as oncomplete] (internal/stream_base_commons.js:66:16)
message: 'write EPIPE',
errno: 'EPIPE',
code: 'NetworkingError',
syscall: 'write',
region: 'eu-west-3',
hostname: 'welive-inc.s3.eu-west-3.amazonaws.com',
retryable: true,
time: 2019-06-17T21:15:46.958Z,
statusCode: 400,
storageErrors: [] }
The frontend doesn't even wait for response and returns this error after couple minutes
net::ERR_EMPTY_RESPONSE
Try overriding default upload size
var limits = {
files: 1, // allow only 1 file per request
fileSize: <Mbs allowed> * 1024 * 1024, // (replace MBs allowed with your desires)
};
then apply it to your multer instance
const upload = multer({
limits: limits,
storage: multerS3({
s3,
bucket: 'welive-inc',
acl: 'public-read',
metadata: function (req, file, cb) {
cb(null, {fieldName: 'TESTING_META_DATA!'});
},
key: function (req, file, cb) {
cb(null, Date.now().toString() + randtoken.uid(16))
}
})
})

Uploading an image in s3 using nodejs

I'm trying to upload an image to s3 using node js. I'm using multer-s3.
When I try to open the image from s3 it shows"Preview not available.Your file may be corrupted".I tried fs too but still the same result.
services/file-upload.js
const s3Config = new aws.S3({
secretAccessKey: config.awsCredentials.secretAccessKey,
accessKeyId: config.awsCredentials.accessKeyId,
region: config.awsCredentials.region,
bucket: 'bucketname',
});
const fileFilter = (req, file, cb) => {
if (file.mimetype === 'image/jpeg' || file.mimetype === 'image/png') {
cb(null, true)
} else {
cb(null, false)
}
}
const multerS3Config = multerS3({
s3: s3Config,
bucket: 'bucketname',
metadata: function (req, file, cb) {
cb(null, { fieldName: file.fieldname });
},
key: function (req, file, cb) {
console.log(file)
cb(null, new Date().toISOString() + '-' + file.originalname)
}
});
const upload = multer({
storage: multerS3Config,
fileFilter: fileFilter,
limits: {
fileSize: 1024 * 1024 * 5 // we are allowing only 5 MB files
}
})
controller.js
const upload = require('../services/file-upload');
var Uploader = require('s3-image-uploader');
const singleUpload = upload.single('file');
singleUpload(req, res, function(err) {
if (err) {
return res.status(422).send({errors: [{title: 'Image Upload Error', detail: err.message}] });
}
return res.json({'imageUrl': "uploaded successfully"});
});

I am not able to upload large files using multer-s3. It is not giving me any error as well.

I am not able to upload large files using multer-s3. It is not giving me any error as well. It just doesn't upload the file, doesn't even enters the callback and gets timeout. Any way to handle uploading large files to s3 Bucket?
I am using it like this:
var uploadSingle = upload.single('uploadFile');
router.post('/uploadVideo',function(req,res,next){
uploadSingle(req,res,function(err){
// doesn't come here if the file is large
if(err){
//Error Response , Error while uploading Module PDF;
}
else{
//handling file upload
// success response
}
});
}
I had the same issue and after researching this page I found that I need to add contentLength as one of the parameters. Its value is for the length in bytes.
const s3 = new AWS.S3({
accessKeyId: process.env.S3_ACCESS_KEY_ID,
secretAccessKey: process.env.S3_SECRET_ACCESS_KEY
});
var upload = multer({
storage: multerS3({
s3: s3,
bucket: 'myBucket',
contentType: multerS3.AUTO_CONTENT_TYPE,
contentLength: 500000000,
metadata: function (req, file, cb) {
cb(null, {fieldName: file.fieldname});
},
key: function (req, file, cb) {
cb(null, file.originalname);
}
})
});
router.post('/uploadToS3', upload.array('photos', 30), function(req, res, next) {
res.send({"message": 'Successfully uploaded ' + req.files.length + ' files!'});
})

Transform images into thumbnails before uploading to S3 in nodejs

I have been trying multer-s3 for many hours, But i'm failing in creating thumbnails. Can anyone please tell me how to run it?
Following is my code:
var upload = multer({
storage: multerS3({
s3: s3,
bucket: 'test',
// shouldTransform: function (req, file, cb) {
// cb(null, /^image/i.test(file.mimetype))
// },
acl: 'public-read',
contentType: multerS3.AUTO_CONTENT_TYPE,
shouldTransform : function (req, file, cb) {
console.log('in should transform ', file)
cb(null, /^image/i.test(file.mimetype))
},
transforms: [{
id: 'original',
key: function (req, file, cb) {
console.log('original')
cb(null, "original")
},
transform: function (req, file, cb) {
console.log('original1')
cb(null, sharp().jpg())
}
}, {
id: 'thumbnail',
key: function (req, file, cb) {
console.log('thumbnail')
cb(null, "thumbnail")
},
transform: function (req, file, cb) {
console.log('thumbnail1')
cb(null, file.resize(100, 100).jpg())
}
}]
})
})
app.post('/upload', upload.single('image'), extendTimeout, function(req, res, next) {
console.log('filessss ', req.file )
res.send('Successfully uploaded ' + req.file + ' files!')
})
Original image is uploaded successfully but resized image is not. Can anyone please guide me?
Thanks
There is a typo in thumbnail's transform method.
Instead of
cb(null, file.resize(100, 100).jpg())
should be
cb(null, sharp().resize(100, 100).jpg())

Resources