I am trying to send files from the client to the server using Multer. So far so good. The issue starts when filtering the files that are coming in.
Ideally, I'd like to filter files by their hash (a simple SHA-1 will be enough) so that the server doesn't download a file it already has. There could be different files with the same name so filtering by name wouldn't work.
I wrote this filter function to use as the fileFilter
parameter for Multer.
function filter(req:any, file:any, cb:any) {
readdir("src/backend/uploads", { withFileTypes: true }, (err, files) => {
if(err) cb(err);
files.forEach(f => {
if(req.body.hash === utils.hash(req.file)) {
console.log(`File ${file.originalname} already exists!`)
cb(null, false);
}
})
})
cb(null, true);
}
After some looking around I came to the realization that the Multer config functions are executed before the body of the request is populated and the file even received. However since the file
parameter only contains metadata like the mimetype or the original name.
Is it possible to make Multer wait for the request to be populated before executing the config functions?
Here's the whole Multer config file for context
import multer from "multer";
import { readdir } from "fs";
import { utils } from "./utils";
/**
* Storage engine config
* Use the cb function to pass the resul
* and go to the next stage
*
* Destination : Where it saves the files
* filename : How to name the files
*/
const storage = multer.diskStorage({
destination: function(req:any, file:any, cb:any) {
cb(null, "src/backend/uploads")
},
filename: async function(req:any, file:any, cb:any) {
cb(null, file.originalname)
}
})
/**
* Middleware function to filter entering files
* filter by hash
*
* @param req : HTTP request object, body empty
* @param file : basic information on the file
* @param cb : callback function to call
*/
function filter(req:any, file:any, cb:any) {
readdir("src/backend/uploads", { withFileTypes: true }, (err, files) => {
if(err) cb(err);
files.forEach(f => {
if(req.body.hash === utils.hash(req.file)) {
console.log(`File ${file.originalname} already exists!`)
cb(null, false);
}
})
})
cb(null, true);
}
export const uploader = multer({ storage: storage, fileFilter: filter }).single('file')