FightForJustice
FightForJustice

Reputation: 355

Amazon S3 bucket file upload response is not available

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
    }
}

Upvotes: 2

Views: 2331

Answers (2)

Hrishikesh Baidya
Hrishikesh Baidya

Reputation: 567

I have whole code using multer and aws-sdk

  1. 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");
    
  2. 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

Upvotes: 1

Oluwafemi Sule
Oluwafemi Sule

Reputation: 38982

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
  })
});

Upvotes: 0

Related Questions