4

Im setting up a server to run a blackjack game and I want to store profile pictures on amazon S3 using multer on the backend. However, whenever I try to send an image from my frontend to the backend, my req.file is undefined.

There are many posts with this probelm, but i have done most of what they said and its been to no avail.

my HTML input:

<fieldset>
                <legend>Create Account</legend>
                Username:<input type="text" id="createUser"><br>
                Password:<input type="password" id="createPW"><br>
                Screen Name: <input type="text" id="createScreen"><br>
                Profile Picture: <input type="file" enctype="multipart/form-data"  id="avatar" name="avatar" accept="image/png, image/jpeg">
                <button id="createAccountButton">Submit</button>
            </fieldset>

my frontend fetch (pure js):

fetch(ec2+"/image-upload", {method: "POST", body: file}).then(checkStatus).catch(function(e){console.log(e);});

my backend: server.js

const singleUpload = upload.single('avatar');

app.post('/image-upload',function(req, res) {
    console.log(req.file);
    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});
    });
  })

upload:

var upload = multer({
  storage: multerS3({
    s3: s3,
    bucket: 'cloud-bj-bucket',
    acl: 'public-read',
    metadata: function (req, file, cb) {
      cb(null, {fieldName: 'TESTING_METADATA'});
    },
    key: function (req, file, cb) {
      cb(null, file.filename);
    }
  })
})

The error is within the backend part

EDIT: here is how i am getting the image from the html

var file = document.getElementById("avatar").files[0];

fetch(ec2+"/image-upload", {method: "POST", body: file}).then(checkStatus).catch(function(e){console.log(e);});

1 Answers1

2

It's because you're trying to access req.file before upload.single is executed. Simply chain the middleware like:

const singleUpload = upload.single('avatar');

app.post('/image-upload', singleUpload, function(req, res) { // <-- mount it here
  console.log(req.file)
  // rest of the code
}

You could use FormData to set the correct headers and use it in your fetch call. However you would need a form element for that.

var file = document.getElementsByTagName("form");
var data = new FormData(file)
fetch(ec2+"/image-upload", {
  method: "POST",
  body: data
})

The easiest option would be to have form element and call the api directly without getting fetch involved:

<form action="/image-upload" method="POST" enctype="multipart/form-data">
  <fieldset>
    <legend>Create Account</legend>
    Username:<input type="text" id="createUser">
    Password:<input type="password" id="createPW">
    Screen Name: <input type="text" id="createScreen">
    Profile Picture: <input type="file"  id="avatar" name="avatar" accept="image/png, image/jpeg">
    <button type="submit" id="createAccountButton">Submit</button>
  </fieldset>
</form>
1565986223
  • 6,420
  • 2
  • 20
  • 33