Hello guys,
I'm trying to submit a multipart form data to a nodejs server, and I'd like to check if all required fields exist in the form, before the upload starts.
However, multer only finish the form parsing after the upload is complete.
Anyone know how I can check the form fields before the upload? I'm not interested in uploading files first, and only then check if the other form data is valid.
Thanks guys!
This might actually be quite a challenge since the browser is free to (and often does, see below) send files and fields mixed and in any order. This means that multer can't read the fields first, and then decide if it should continue with the files or bail on the stream.
However, there is a "workaround" if you really need it. If you construct a FormData object with javascript on the client, you could potentially let the browser know in which order you want it to send things. Now, as fair as I know, the spec dosen't say that the browser should send things in the same order that you .append() them, but it seems to be working for now.
The second part now is to somehow instruct multer to discontinue if there is a problem with the fields. I'm pretty sure that it's currently possible with all the hooks that we expose. But we are working on minimizing that in #131. I don't think it's that interesting if it's possible or not, but wether there is a clear path of expressing this intent or not.
With the new code, I actually think that there is. You could use the fileFilter feature to express that "only accept files if valid fields has preceded it". Something like this:
let multer = require('multer')
function hasRequiredFields (fields) {
// 1. Implement this!
}
let upload = multer({
fileFilter: function (req, file, cb) {
cb(null, hasRequiredFields(req.body))
}
})
app.post('/upload', upload, function (req, res) {
// 2. Handle the request
})
// 3. ????
// 4. PROFIT!!
Multer 1.0.0 is now released and you should be able to use the workaround suggested above.
Unfortunately there is nothing we can do about the order in which the browsers send things.
Hi @LinusU , As you said above.
app.post('/upload', upload, function (req, res) {
// 2. Handle the request
})
the "upload" looks like a router middleware, and the router middleware required to be a function. But the "update" is an object In fact.
the source code as follow.
function multer (options) {
if (options === undefined) {
return new Multer({})
}
if (typeof options === 'object' && options !== null) {
return new Multer(options)
}
throw new TypeError('Expected object for argument options')
}
SO, I got an error.
Error: Route.post() requires callback functions but got a [object Object]
Yeah I posted the workaround before 1.0 was released so it didn't account for that syntax.
You need to change it into one of the new functions for accepting files, e.g. upload.single('avatar'). Which one you should choose depends on what files you want to accept, check the documentation for more information.
Is there any work around besides the one above ? @LinusU
I want to use my Joi middleware but if the multer middleware comes before it then req.body is undefined meaning that its not being parsed.
For example:
router.post('/savings/', idValidaiton.validateIdKey, validCompany,parser.single('imageUrl'),
createSavings )
The above wont work but the below works:
router.post('/savings/', parser.single('imageUrl'),idValidaiton.validateIdKey, validCompany,
createSavings )
So basically the image is uploaded before the req.body is validate
My parse Middleware looks like this:
const multer = require('multer')
const cloudinary = require('cloudinary')
const cloudinaryStorage = require('multer-storage-cloudinary')
cloudinary.config({
cloud_name: process.env.CLOUD_NAME,
api_key: process.env.CLOUD_API_KEY,
api_secret: process.env.CLOUD_API_SECRET
})
const storage = cloudinaryStorage({
cloudinary: cloudinary,
folder: 'ratehogs',
allowedFormats: ['jpg', 'png', 'jpeg'],
transformation: [{ width: 500, height: 500, crop: 'limit' }]
})
const parser = multer({ storage: storage })
module.exports = parser
Trying to see how i can incorporate you solution
This might actually be quite a challenge since the browser is free to (and often does, see below) send files and fields mixed and in any order. This means that multer can't read the fields first, and then decide if it should continue with the files or bail on the stream.
However, there is a "workaround" if you really need it. If you construct a
FormDataobject with javascript on the client, you could potentially let the browser know in which order you want it to send things. Now, as fair as I know, the spec dosen't say that the browser should send things in the same order that you.append()them, but it seems to be working for now.The second part now is to somehow instruct multer to discontinue if there is a problem with the fields. I'm pretty sure that it's currently possible with all the hooks that we expose. But we are working on minimizing that in #131. I don't think it's that interesting if it's possible or not, but wether there is a clear path of expressing this intent or not.
With the new code, I actually think that there is. You could use the
fileFilterfeature to express that "only accept files if valid fields has preceded it". Something like this:let multer = require('multer') function hasRequiredFields (fields) { // 1. Implement this! } let upload = multer({ fileFilter: function (req, file, cb) { cb(null, hasRequiredFields(req.body)) } }) app.post('/upload', upload, function (req, res) { // 2. Handle the request }) // 3. ???? // 4. PROFIT!!
What if I don't attach file at all? Then this fileFilter won't be fired meaning req without file will be forwarded next
Will test it out and advise
Will test it out and advise
u were able to make that work?
suggestion: what about sending a request to validate only text fields first and if validation passes, then you send another request with the validated data and the file you want to upload
Most helpful comment
This might actually be quite a challenge since the browser is free to (and often does, see below) send files and fields mixed and in any order. This means that multer can't read the fields first, and then decide if it should continue with the files or bail on the stream.
However, there is a "workaround" if you really need it. If you construct a
FormDataobject with javascript on the client, you could potentially let the browser know in which order you want it to send things. Now, as fair as I know, the spec dosen't say that the browser should send things in the same order that you.append()them, but it seems to be working for now.The second part now is to somehow instruct multer to discontinue if there is a problem with the fields. I'm pretty sure that it's currently possible with all the hooks that we expose. But we are working on minimizing that in #131. I don't think it's that interesting if it's possible or not, but wether there is a clear path of expressing this intent or not.
With the new code, I actually think that there is. You could use the
fileFilterfeature to express that "only accept files if valid fields has preceded it". Something like this: