3

i m unable to figure out how to use req.body.fname as the name for the file, even tried using middleware but req.body was empty.

var storage = multer.diskStorage({
  destination: function (req, file, cb) {
    cb(null, path);
  },
  filename: function (req, file, cb) {
    cb(null, req.body.fname)  // undefined 
  }
})
var upload = multer({ storage: storage })

app.get('/upload', upload.single('fname'), (req,res)=>{
  .......
})

i m unable to figure out how to fetch fname in fileName
index.html

<form action="/upload" method="POST" enctype= "multipart/form-data">
  <input type="text" name="fname">
  <input type="file" name="pic">
  <input type = "submit">
</form>

3 Answers3

5

This is not an elegant way, but it's better than nothing.


What multer can't do


As far as I know, Multer sends the req.body fields only after the actual file has been sent. So when you name the files, you won't have access to the fields. And as the enctype is set to multipart, Body Parser will cease to work as well.

Where can you get req.body


Although late, Multer actually sends the req.body fields after all. These will be accessible after uploading the files:
app.post('/upload', (req, res) => {
  upload(req, res, function (err) {
    console.log(req.body.fname) // Here it works
  });
});


A simple work-around


Now after we upload the picture, we have a file named "undefined", (BTW you may want to add extension, I'll get to that later.) the path of which we can access through req.file.path. So now we call fs to rename it. It's native to Node.js so there is no need to install. Simply require it before use:
const fs = require('fs');

Then we go back to the uploading process.

app.post('/upload', (req, res) => {
  upload(req, res, function (err) {
    fs.renameSync(req.files.path, req.files.path.replace('undefined', req.body.fname));
    // This get the file and replace "undefined" with the req.body field.
  });
});

I'm assuming that your path to the file don't have a folder called "undefined". In this unlikely case, just name the file something else with Multer and replace that later with fs.renameSync.


Final touch: add extension


If you don't plan on entering extension in the HTML input field, you may want to attach the extension in the naming process. To get the extension, we can use path, which is also native to Node.js and only need to be required:
const path = require('path');

var storage = multer.diskStorage({
  destination: function (req, file, cb) {
    cb(null, path);
  },
  filename: function (req, file, cb) {
    cb(null, req.body.fname + path.extname(file.originalname))
  }
})

Or in the unlikely case you want a ".undefined" extension, just attach the extension later in the fs renaming process.

Hope this solves your problem. Happy coding!

Agustín Dorado
  • 294
  • 2
  • 11
0

multer puts the file first and then takes the body so the name comes after the uploaded file when it comes to submitting forms. the answer I found in the documentation t.ly/dyp9, that the name of the input can be used as well so I take the value of the input and then pass it to the input name of the file uploaded in dom, here is the code

var storage = multer.diskStorage({
  destination: function (req, file, cb) {
    cb(null, path);
  },
  filename: function (req, file, cb) {
    cb(null, file.filename) 
  }
})
<form action="/upload" method="POST" enctype= "multipart/form-data">
  <input type="text" name="fname">
  <input type="file" name="pic">
  <button onclick="submit()" >click me</button>
</form>
<script>
const submit = () => {
  const inputName = document.getElementsByTagName("input")[0].value;
  const pic = document.getElementsByTagName("input")[1];
  pic.name = inputName;
  const form = document.getElementsByTagName("form")[0].submit
  };
</script>
Dharman
  • 30,962
  • 25
  • 85
  • 135
0

I also have this file name problem. I solve it by passing it in query.

  const storage = multer.diskStorage({
  destination: "uploads/",
  filename: (req, file, cb) => {
    cb(null, req.query.filename + path.extname(file.originalname));
  },
});

according to resful api, it is better to put it in params but I just found query convenient and it could also accept multiple queries if there are more than one file.

Zhong Tom
  • 1
  • 1
  • 2