Reputation: 426
I'm writing an application for a client, and they should be able to upload images and documents for a product.
The html form/ fieldset has two file inputs. one for the images and another one for the documents.
input.product-upload-images(
type="file",
multiple="multiple",
value="images",
accept="image/png, image/jpg ,image/jpeg")
input.product-upload-documents(
type="file",
multiple="multiple",
value="Documents",
accept="application/pdf")
In my POST/ PUT controller I want to check with a middleware if all files in the field images[]
are MIME-type image/...
and if all files in the field documents[]
are MIME-type image/pdf
.
I removed some middlewares, like the passport middleware, or the data validation midddleware, to provide an easy to understand example.
const uploadPath = path.join('some', 'path');
const upload = multer({
dest: uploadPath,
fileFilter: (req, file, cb) => {
// filter filetype by field
}
});
const uploadMiddleware = upload.fields([
{name: 'documents[]', maxCount: 10},
{name: 'images[]', maxCount: 10}
]);
// ...
router.post(
'/',
uploadMiddleware,
async (req, res, next) => {
// ...
How can I accomplish the implementation of a file filter, which can filter for a certain field a file type?
Upvotes: 0
Views: 541
Reputation: 107
I will go ahead and modify your code to include the implementation for a fileFilter
callback function for multiple fields upload.
...
const upload = multer({
dest: uploadPath,
fileFilter: (req, file, cb) => {
// filter filetype by field - `file` will all be a single File object
if (['image/png', 'image/jpeg', 'application/pdf'].include(file.mimetype)) {
cb(null, true);
} else {
cb(new Error('unknown file type.'));
}
});
...
It is important to note that in as much as the uploads are fields - where each field can contain multiple file types, multer will dump all fields in the fileFilter callback as individual file object and not as an array, it does this by calling the fileFilter callback for each file. However, in your controller you will have the fields sorted and properly added into an array.
For instance, assuming the documents
field and images
field contains 3 and 2 files respectively then multer will list 5 objects in the fileFilter callback function and in the controller (final middleware handler) create an array of objects with the key documents
and images
: req.files will print the following object.
[Object: null prototype] {
documents: [
{
fieldname: 'documents',
originalname: 'doc.pdf',
encoding: '7bit',
mimetype: 'document/pdf',
...
},
{...},
{...}
],
images: [
{
fieldname: 'image1',
originalname: 'avatar.jpg',
encoding: '7bit',
mimetype: 'image/jpeg',
...
},
{...}
]
}
Note In the below snippet from your code:
const uploadMiddleware = upload.fields([
{name: 'documents[]', maxCount: 10},
{name: 'images[]', maxCount: 10}
]);
I assumed the { name: 'documents[]', maxCount: 10 }
and { name: 'images[]', maxCount: 10 }
to be { name: 'documents', maxCount: 10 } and { name: 'images', maxCount: 10 }
Upvotes: 0
Reputation: 29
You can also specify the destination via a Callback.
const exampleMimeType = 'image'
const storage = multer.destination({
destination: (req, file, cb) => {
if(file.mimeType === exmpleMimeType){
cb(null, `/files/${exampleMimeType}`)
}
}
})
Upvotes: -1