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"});
});
Related
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 });
}
});
};
I am setting static path but getting error : "Error: ENOENT: no such file or directory, open 'C:\dashboard new - Copy\uploads\2019-11-28T08:11:09.164Z1564660431900.jpg'"
const storage = multer.diskStorage({ destination: function(req, file, cb) { let dest = path.join(__dirname, '../../uploads'); cb(null, dest); }, filename: function(req, file, cb) { cb(null, new Date().toISOString() + file.originalname); }});
const fileFilter = (req, file, cb) => { if (file.mimetype === 'image/jpeg' || file.mimetype === 'image/png') { cb(null, true); } else { cb(null, false); }};
const upload = multer({ storage: storage, limits: { fileSize: 1024 * 1024 * 5 }, fileFilter: fileFilter});
router.post("/", upload.single('productImage'), async (req, res, next) => {
try {
cosole.log('hi');
const product = new Product({
_id: new mongoose.Types.ObjectId(),
name: req.body.name,
price: req.body.price,
productImage: req.file.path
});
const saveImage = await product.save();
console.log(saveImage)
res.json(saveImage);
} catch (error) {
console.log(error);
res.json(error);
}
});
How to do this?
I think you need to provide the destination folder as a key and value, something like this(below)
var upload = multer({ dest: 'uploads/' })
You can check out the full multer documentations here
https://expressjs.com/en/resources/middleware/multer.html
I'm trying to upload a file to s3 but it not happening what I expected.
I create a file-helper.js in middleware, that is looks like below
const aws = require('aws-sdk');
const multer = require('multer');
const multerS3 = require('multer-s3');
aws.config.update({
accessKeyID:'XXXXXXXXXXXXXX',
SecretAccessKey:'XXXXXXXXXXXXXXXXXXXXXXXXXXX',
region:'ap-south-1'
});
const s3 = new aws.S3();
const fileFilter = (req, file, cb) => {
if (file.mimetype === 'image/jpeg' || file.mimetype === 'image/png') {
cb(null, true);
} else {
cb(new Error('Invalid file type, only JPEG and PNG is allowed!'), false);
}
}
const upload = multer({
fileFilter,
storage: multerS3({
s3,
bucket: 'demo.moveies.com',
acl: 'public-read',
metadata: function (req, file, cb) {
cb(null, {fieldName: file.fieldname});
},
key: function (req, file, cb) {
cb(null, Date.now().toString())
}
})
})
module.exports = upload;
and my controller file like below
const upload = require('../middleware/file-helper');
const imageUpload = upload.single('image');
exports.fileUpload = async(req,res)=>{
imageUpload(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});
});
}
when hit the API end point it is giving error
{
"errors": [
{
"title": "Image Upload Error",
"detail": "Missing credentials in config"
}
]
}
I'm not able to figure out where I went in wrong in my code. can one help me in this situation
There are typos in your config details. It should be accessKeyId not accessKeyID and secretAccessKey and not SecretAccessKey.
You have used the wrong key SecretAccessKey and accessKeyID, try changing it to secretAccessKey and accessKeyId.
aws.config.update({
accessKeyId:'XXXXXXXXXXXXXX',
secretAccessKey:'XXXXXXXXXXXXXXXXXXXXXXXXXXX',
region:'ap-south-1'
});
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())
}
})
})
I'm using multer ,aws-sdk and multer-s3 packages along with express.
when users edit profile user may change profile picture /avatar or not.
I've passed multer object
multer({storage:
multer.memoryStorage()}).single('profileHeroImageEdit')
if a file with current request then I will upload the file to s3 bucket but I am not getting any response from upload_replace where req.file.location will provide the url of S3 bucket (file's location).
And Inside upload_replace I can get the file I am trying to upload(req.file) but I want the location of uploaded file to S3 bucket .
What I'm missing ? Help will be appreciated
router.put("/:id",multer({ storage:
multer.memoryStorage()}).single('profileHeroImageEdit'),
middleware.checkProfileOwnership,function(req, res){
if(isFileExists(req)==false){
delete req.body.profileHeroImage
}
else{
console.log('file has')
var upload_replace = multer({
limits:{
fileSize:MAX_FILE_SIZE,
files:1
},
storage: multerS3({
s3: photoBucket,
bucket: BucketName,
acl: 'public-read',
metadata: function (req, file, cb) {
cb(null, { fieldName: file.fieldname });
},
key: function (req, file, cb) {
cb(null,Date.now().toString())
}
})
}).single('profileHeroImageEdit')
upload_replace(req, res, function (err,log) {
console.log('request log')
console.log(req.file.location)
console.log()
});
}
Profile.findByIdAndUpdate(req.params.id, req.body.profile, function(err, updatedProfile){
if (err){
res.redirect("/profiles");
} else {
res.redirect("/profiles/" + req.params.id);
}
});
});
function isFileExists(request){
if(request.file)
{
return true
}
else{
return false
}
}
I have whole code using multer and aws-sdk
include this files and npm install all
//aws s3 packages
const aws = require("aws-sdk");
const multerS3 = require("multer-s3");
const multer = require("multer");
const path = require("path");
then
//profile image upload start
const s3 = new aws.S3({
accessKeyId: "***",
secretAccessKey: "***",
Bucket: "***"
});
//Singe profile image upload
const profileImgUpload = multer({
storage: multerS3({
s3: s3,
bucket: "***",
acl: "public-read",
key: function(req, file, cb) {
cb(
null,
path.basename(file.originalname, path.extname(file.originalname)) +
"-" +
Date.now() +
path.extname(file.originalname)
);
}
}),
limits: { fileSize: 2000000 }, // In bytes: 2000000 bytes = 2 MB
fileFilter: function(req, file, cb) {
checkFileType(file, cb);
}
}).single("profileImage");
// getExtension of file by this function
function getExtension(filename) {
var parts = filename.split(".");
return parts[parts.length - 1];
}
//checkfile type of input function
function checkFileType(file, cb) {
const ext = getExtension(file.originalname);
switch (ext.toLowerCase()) {
case "jpeg":
case "jpg":
case "png":
case "gif":
return cb(null, true);
}
cb("Error: Images Only!");
}
router.post(
"/image",
passport.authenticate("jwt", { session: false }),
(req, res) => {
profileImgUpload(req, res, error => {
if (error) {
res.json({ error: error });
} else {
//here we can get req.body
const userDp = {};
//end of getting values
// If File not found then dont store anything
if (req.file !== undefined) userDp.dpUrl = req.file.location;
// Save the file name into database into profile model
User.findOne({ email: req.user.email }).then(user => {
if (user) {
// Update
User.findOneAndUpdate(
{ email: req.user.email },
{ $set: userDp },
{ new: true }
).then(user => res.json(user));
} else {
res.json({ msg: "not able not update data" });
}
});
}
});
}
);
3.need to send data from react frontend by using
const data = new Formdata();
data.append()
and by including headers also
Add a listener for when the OutgoingMessage to upload the photo to S3 is completed. The on-finished library is handy for this.
const onFinished = require('on-finished');
const print = process._rawDebug;
uploadReplace(req, null, function (err) {
onFinished(req, function () {
if (err) print(err);
print(req.file.location);
// Other things can be done here
})
});