I want to upload images on the website built on React
. I have issue with backend Node.js
code.
Code:
const multer = require("multer");
// Check if the directory exists, if not, create it
const directory = path.join(__dirname, "../src/assets/img/images");
if (!fs.existsSync(directory)) {
fs.mkdirSync(directory);
}
console.log("Directory: ", directory);
// Set up multer storage and file filter
// Set up multer middleware
const uploadMulter = multer({
storage: multer.diskStorage({
destination: (req, file, cb) => {
cb(null, directory); // Save files to the "src/assets/img/images" directory
},
filename: (req, file, cb) => {
cb(null, file.originalname); // Use the original file name
}
}),
fileFilter: (req, file, cb) => {
// Accept only image files
if (file.mimetype.startsWith("image/")) {
console.log("Success!!!");
cb(null, true);
} else {
console.log("Error!!!!");
cb(new Error("Invalid file type. Only image files are allowed."));
}
}
});
interface FileContent {
fileName: string;
content: string;
type: string;
}
// Route for file upload
app.post("/upload/images", uploadMulter.array("files[]"), (req, res) => {
// Retrieve the uploaded files from req.files array
const files = req.files;
// You can now process the uploaded files (e.g., save to database, manipulate, etc.)
// For example, if you want to read the content of each file:
const fileContents: FileContent[] = [];
files.forEach((file) => {
console.log("FileError: ", file.fileError);
console.log("file.fileError.message: ", file.fileError.message);
const data = fs.readFileSync(file.path, "binary");
fileContents.push({fileName: file.originalname, content: Buffer.from(data, "binary").toString("base64"), type: file.mimetype}); //, fileError: error
});
// Send response
res.status(200).json({files: fileContents});
});
At this moment, it just prints to the server console. I want to print this error to a user in case a user selects the text file instead of an image:
Invalid file type. Only image files are allowed.
But it fails for me with this error: POST http://localhost:3000/upload/images 500 (Internal Server Error).
Full error log:
Error: Invalid file type. Only image files are allowed. at fileFilter (C:\wamp64\www\insurance_site\build_server\server.js:4609:5399) at wrappedFileFilter (C:\wamp64\www\insurance_site\node_modules\multer\index.js:44:7) at Multipart.<anonymous> (C:\wamp64\www\insurance_site\node_modules\multer\lib\make-middleware.js:107:7) at Multipart.emit (events.js:400:28) at Multipart.emit (domain.js:475:12) at HeaderParser.cb (C:\wamp64\www\insurance_site\node_modules\busboy\lib\types\multipart.js:358:14) at HeaderParser.push (C:\wamp64\www\insurance_site\node_modules\busboy\lib\types\multipart.js:162:20) at SBMH.ssCb [as _cb] (C:\wamp64\www\insurance_site\node_modules\busboy\lib\types\multipart.js:394:37) at feed (C:\wamp64\www\insurance_site\node_modules\streamsearch\lib\sbmh.js:219:14) at SBMH.push (C:\wamp64\www\insurance_site\node_modules\streamsearch\lib\sbmh.js:104:16)
Any ideas how to return the proper message back to a user?
Ok. I have fixed this issue by removing fileFilter
from multer
. Also, I added checks for image types in the app.post("/upload/images"...
method.
This will not prevent file from upload to a server but I can display the error message "Invalid file type. Only image files are allowed." to a user and remove file if it's not an image.
Code:
const uploadMulter = multer({
storage: multer.diskStorage({
destination: (req, file, cb) => {
cb(null, directory);
},
filename: (req, file, cb) => {
cb(null, file.originalname);
}
})
});
app.post("/upload/images", uploadMulter.array("files[]"), (req, res) => {
const files = req.files;
const filteredFiles = files.filter(file => file.mimetype.startsWith("image/"));
if (filteredFiles.length !== files.length) {
files.forEach((file) => {
fs.unlink(file.path, (error) => {});
});
return res.status(400).json({error: "Invalid file type. Only image files are allowed."});
}
const fileContents: FileContent[] = [];
filteredFiles.forEach((file) => {
const data = fs.readFileSync(file.path, "binary");
fileContents.push({fileName: file.originalname, content: Buffer.from(data, "binary").toString("base64"), type: file.mimetype, path: file.path, successMsg: "Image(s) uploaded successfully."});
});
res.status(200).json({files: fileContents});
});
It works well. This issue is resolved.