MVC架构下Node.js使用Multer实现CSV文件上传时req.body未定义的问题求助
req.body Undefined Issue with Multer in Node.js MVC Project Hey there, let's figure out why you're getting req.body as undefined when trying to upload your CSV files. I've gone through your code and spotted a few key issues that are causing this problem—let's break them down and fix them step by step.
The Core Problem
When dealing with file uploads using multipart/form-data (required for file uploads), Express's default body parsers (express.json()/express.urlencoded()) can't parse the request body. Multer is responsible for parsing both the file and text fields in these requests, but your current setup isn't using Multer as a proper Express middleware, which is why req.body isn't being populated.
Additionally, you're initializing Multer inside your controller's route handler, which is inefficient and can lead to unexpected behavior since a new Multer instance is created on every request.
Step-by-Step Fixes
1. Refactor Multer Configuration to Be Reusable
First, move your Multer setup out of the route handler and create a reusable instance. This ensures we only initialize Multer once, and it properly acts as middleware to parse the request.
Add this to the top of your controller file (or a separate config file for better organization):
const multer = require('multer'); const fs = require('fs'); // Ensure the upload directory exists (prevents "no such file or directory" errors) const uploadDir = "./public/images/files/"; if (!fs.existsSync(uploadDir)) { fs.mkdirSync(uploadDir, { recursive: true }); } // Configure Multer storage const storage = multer.diskStorage({ destination: function (req, file, cb) { // Now req.body.pid will be available here because Multer has parsed the text fields const pid = req.body.pid; console.log(pid, "janko"); cb(null, uploadDir); }, filename: function(req, file, cb) { const datetimestamp = Date.now(); // Simplify extension extraction const fileExt = file.originalname.split(".").pop(); cb(null, `${file.fieldname}-${datetimestamp}.${fileExt}`); } }); // Fix file filter logic (you had typos in allowed extensions: "cs" → "csv", "xlx" → "xlsx") const fileFilter = function(req, file, callback) { const allowedExtensions = ["csv", "xlsx"]; const fileExt = file.originalname.split(".").pop().toLowerCase(); if (!allowedExtensions.includes(fileExt)) { return callback(new Error("Invalid file type! Only CSV and XLSX files are allowed.")); } callback(null, true); }; // Create a reusable Multer upload instance const upload = multer({ storage: storage, fileFilter: fileFilter }).single('csvFile');
2. Update the Controller Route Handler
Modify your Documents controller function to rely on the reusable Multer instance, and add proper validation and error handling:
async (req, res) => { try { // First, validate that pid is present (now that Multer has parsed req.body) if (!req.body.pid) { console.log(req.body, "test"); return res.status(400).json({ error: "pid is a required field" }); } // At this point, the file has already been uploaded by the Multer middleware const uploadedFileName = req.file.filename; const pid = req.body.pid; // Add your MySQL database logic here to save pid and filename // Example: // await db.query('INSERT INTO documents (pid, filename) VALUES (?, ?)', [pid, uploadedFileName]); res.status(200).json({ message: "File uploaded successfully", pid: pid, filename: uploadedFileName }); } catch (err) { console.error(err); res.status(500).json({ error: "Server error occurred while processing your request" }); } }
3. Update the Route to Use Multer as Middleware
Now, add the Multer instance as middleware to your route so it parses the request before hitting your controller:
// Import the upload instance and your controller function const { upload, Documents } = require('./path/to/signupController'); router.post("/Documents", upload, Documents);
Key Notes for Your Node.js Journey
- Always use Multer as middleware: This ensures the request body (including text fields like
pid) is parsed before your controller runs. - Validate file extensions correctly: Your original code had typos (
csinstead ofcsv,xlxinstead ofxlsx) which would have blocked valid files. - Ensure upload directories exist: Use
fs.mkdirSyncwithrecursive: trueto avoid errors if the directory doesn't exist yet. - Avoid creating new Multer instances per request: Reusing instances is more efficient and avoids unexpected bugs.
Testing the Fix
To verify this works:
- Use Postman or a frontend form to send a
POSTrequest to/Documentswith:Content-Type: multipart/form-data- A text field named
pidwith your desired value - A file field named
csvFilewith your CSV file
- Check your upload directory to confirm the file is saved, and your console should log the
pidcorrectly.
内容的提问来源于stack exchange,提问作者fungusblacky

