Node.js中用Multer上传图片后,Imagemin压缩失败求助
Let's break down the problems in your code and fix them step by step:
1. Imagemin is Asynchronous – You're Not Waiting for It to Finish
Imagemin returns a promise, but your current code doesn't handle it at all. This means the compression process might not complete before the request ends, and you're missing error feedback that could tell you what's wrong.
Fix with Promise Handling:
app.post('/upload', (req, res) => { upload(req, res, (err) => { if (err) { res.render('picupload', { msg: err }); } else { if (req.file == undefined) { res.render('picupload', { msg: 'Error: No File selected!' }); } else { console.log(req.file); imagemin([`uploads/${req.file.filename}`], 'uploads/compressed', { plugins: [ imageminJpegtran(), imageminPngquant({ quality: '65-80' }) // Fixed typo here ] }) .then(compressedFiles => { console.log('Compression complete:', compressedFiles); res.render('picupload', { msg: 'File uploaded and compressed successfully!', file: `/uploads/compressed/${req.file.filename}` }); }) .catch(compressErr => { console.error('Compression failed:', compressErr); res.render('picupload', { msg: `Error compressing file: ${compressErr.message}` }); }); } } }); });
2. Invalid Quality Parameter in imageminPngquant
Your original code has quality: '65-80...' – the extra trailing dots are invalid syntax. Remove them to use the correct range format '65-80'.
3. Ensure the Output Directory Exists
Imagemin won't automatically create the uploads/compressed folder if it doesn't exist. Add code to check and create it before running compression:
First, require the filesystem module at the top of your file:
const fs = require('fs');
Then, add this before calling Imagemin:
const outputDir = 'uploads/compressed'; if (!fs.existsSync(outputDir)) { fs.mkdirSync(outputDir, { recursive: true }); }
4. Optional: Refactor to Async/Await for Cleaner Code
If you prefer a more readable approach, you can wrap the Multer callback in a promise and use async/await:
app.post('/upload', async (req, res) => { try { // Wait for Multer to finish uploading await new Promise((resolve, reject) => { upload(req, res, (err) => err ? reject(err) : resolve()); }); if (!req.file) { return res.render('picupload', { msg: 'Error: No File selected!' }); } console.log(req.file); // Create output directory if needed const outputDir = 'uploads/compressed'; if (!fs.existsSync(outputDir)) { fs.mkdirSync(outputDir, { recursive: true }); } // Run compression const compressedFiles = await imagemin( [`uploads/${req.file.filename}`], outputDir, { plugins: [ imageminJpegtran(), imageminPngquant({ quality: '65-80' }) ] } ); console.log('Compressed files:', compressedFiles); res.render('picupload', { msg: 'File uploaded and compressed successfully!', file: `/uploads/compressed/${req.file.filename}` }); } catch (err) { console.error('Process failed:', err); res.render('picupload', { msg: err.message }); } });
Quick Checks to Verify
- Double-check you've installed all dependencies:
npm install multer imagemin imagemin-jpegtran imagemin-pngquant - Confirm the original uploaded file exists in the
uploadsdirectory before compression runs - Check your console for error messages (the new catch blocks will log these now)
Content of the question is from Stack Exchange, question author roh_dev

