How to fix "MulterError: Unexpected field" in a nodejs express server? - javascript

I'm setting up a server to upload zip files from the client. The server runs with express and multer to do this. When uploading a file, the server throws a "MulterError: Unexpected field" error and I cannot figuere out what is cousing it.
I've tried with png images and It works just fine. But with the zip files it just doesn't work.
const multerConfig = {
//specify diskStorage (another option is memory)
storage: multer.diskStorage({
//specify destination
destination: function(req, file, next){
next(null, './public/zip-storage');
},
//specify the filename to be unique
filename: function(req, file, next){
console.log(file);
const ext = file.mimetype.split('/')[1];
//set the file fieldname to a unique name containing the original name, current datetime and the extension.
next(null, file.fieldname + '-' + Date.now() + '.'+ext);
}
}),
// filter out and prevent non-image files.
fileFilter: function(req, file, next){
if(!file){
next();
}
// only permit zip mimetypes
const zip = file.mimetype.startsWith('application');
if(zip){
console.log('zip uploaded');
next(null, true);
}else{
console.log("file not supported")
errorReq = true;
return next();
}
}
};
/* ROUTES
**********/
app.get('/', function(req, res){
res.render('index.html');
});
var errorDetection = function(){
if(!errorReq){
errorReq = false;
return('complete.html');
} else{
errorReq = false;
return('errorupload.html');
}
}
app.post('/upload', multer(multerConfig).single('photo'),function(req, res){
//Here is where I could add functions to then get the url of the new photo
//And relocate that to a cloud storage solution with a callback containing its new url
//then ideally loading that into your database solution. Use case - user uploading an avatar...
res.redirect('complete.html');
}
);
// RUN SERVER
app.listen(port,function(){
console.log(`Server listening on port ${port}`);
});
This is the error:
MulterError: Unexpected field
at wrappedFileFilter (/home/axentiva-miguel/Documentos/ServerAPP/node_modules/multer/index.js:40:19)
at Busboy.<anonymous> (/home/axentiva-miguel/Documentos/ServerAPP/node_modules/multer/lib/make-middleware.js:114:7)
at emitMany (events.js:147:13)
at Busboy.emit (events.js:224:7)
at Busboy.emit (/home/axentiva-miguel/Documentos/ServerAPP/node_modules/busboy/lib/main.js:38:33)
at PartStream.<anonymous> (/home/axentiva-miguel/Documentos/ServerAPP/node_modules/busboy/lib/types/multipart.js:213:13)
at emitOne (events.js:116:13)
at PartStream.emit (events.js:211:7)
at HeaderParser.<anonymous> (/home/axentiva-miguel/Documentos/ServerAPP/node_modules/dicer/lib/Dicer.js:51:16)
at emitOne (events.js:116:13)

In the code
app.post('/upload', multer(multerConfig).single('photo'),function(req, res){
//Here is where I could add functions to then get the URL of the new photo
//And relocate that to a cloud storage solution with a callback containing its new URL
//then ideally loading that into your database solution. Use case - user uploading an avatar...
res.redirect('complete.html');
}
I was putting the value single('photo'), when in the HTML form I sent, a 'zip' value in there. Changing that made the code work as expected :)

Related

import a CSV file to MySQL [duplicate]

This question already has answers here:
using (-) dash in mysql table name
(2 answers)
Closed 1 year ago.
I'm a beginner in nodejs and I'm trying to import a CSV file to MySQL
the connect work successfully but when I upload the file it gives an error
I do this :
//use express static folder
app.use(express.static("./public"))
// body-parser middleware use
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({
extended: true
}))
db.connect(function (err) {
if (err) {
return console.error('error: ' + err.message);
}
console.log('Connected to the MySQL server.');
})
//! Use of Multer
var storage = multer.diskStorage({
destination: (req, file, callBack) => {
callBack(null, './uploads/')
},
filename: (req, file, callBack) => {
callBack(null, file.fieldname + '-' + Date.now() + path.extname(file.originalname))
}
})
var upload = multer({
storage: storage
});
//! Routes start
//route for Home page
app.get('/', (req, res) => {
res.sendFile(__dirname + '/index.html');
});
//#type POST
// upload csv to database
app.post('/uploadfile', upload.single("uploadfile"), (req, res) =>{
UploadCsvDataToMySQL(__dirname + '/uploads/' + req.file.filename);
console.log('CSV file data has been uploaded in mysql database ' + err);
});
function UploadCsvDataToMySQL(filePath){
let stream = fs.createReadStream(filePath);
let csvData = [];
let csvStream = csv
.parse()
.on("data", function (data) {
csvData.push(data);
})
.on("end", function () {
// Remove Header ROW
csvData.shift();
// Open the MySQL connection
db.connect((error) => {
if (error) {
console.error(error);
} else {
let query = 'INSERT INTO files (File-ID, File_Name) VALUES ?';
db.query(query, [csvData], (error, response) => {
console.log(error || response);
});
}
});
// delete file after saving to MySQL database
// -> you can comment the statement to see the uploaded CSV file.
fs.unlinkSync(filePath)
});
stream.pipe(csvStream);
}
//create connection
const PORT = process.env.PORT || 8000
app.listen(PORT, () => console.log(`Server is running at port ${PORT}`))
but it's given me this error:
ReferenceError: err is not defined
at C:\Users\DELL\Desktop\Advanced\AdvancedSeE\dbmanager\index.js:80:72
at Layer.handle [as handle_request] (C:\Users\DELL\Desktop\Advanced\AdvancedSeE\dbmanager\node_modules\express\lib\router\layer.js:95:5)
at next (C:\Users\DELL\Desktop\Advanced\AdvancedSeE\dbmanager\node_modules\express\lib\router\route.js:137:13)
at Array. (C:\Users\DELL\Desktop\Advanced\AdvancedSeE\dbmanager\node_modules\multer\lib\make-middleware.js:53:37)
at listener (C:\Users\DELL\Desktop\Advanced\AdvancedSeE\dbmanager\node_modules\on-finished\index.js:169:15)
at onFinish (C:\Users\DELL\Desktop\Advanced\AdvancedSeE\dbmanager\node_modules\on-finished\index.js:100:5)
at callback (C:\Users\DELL\Desktop\Advanced\AdvancedSeE\dbmanager\node_modules\ee-first\index.js:55:10)
at IncomingMessage.onevent (C:\Users\DELL\Desktop\Advanced\AdvancedSeE\dbmanager\node_modules\ee-first\index.js:93:5)
at IncomingMessage.emit (node:events:341:22)
at endReadableNT (node:internal/streams/readable:1294:12)
Error: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '-ID, File_Name) VALUES ('112', 'test2')' at line 1
at Packet.asError (C:\Users\DELL\Desktop\Advanced\AdvancedSeE\dbmanager\node_modules\mysql2\lib\packets\packet.js:728:17)
at Query.execute (C:\Users\DELL\Desktop\Advanced\AdvancedSeE\dbmanager\node_modules\mysql2\lib\commands\command.js:29:26)
at Connection.handlePacket (C:\Users\DELL\Desktop\Advanced\AdvancedSeE\dbmanager\node_modules\mysql2\lib\connection.js:456:32)
at PacketParser.onPacket (C:\Users\DELL\Desktop\Advanced\AdvancedSeE\dbmanager\node_modules\mysql2\lib\connection.js:85:12)
at PacketParser.executeStart (C:\Users\DELL\Desktop\Advanced\AdvancedSeE\dbmanager\node_modules\mysql2\lib\packet_parser.js:75:16)
at Socket. (C:\Users\DELL\Desktop\Advanced\AdvancedSeE\dbmanager\node_modules\mysql2\lib\connection.js:92:25)
at Socket.emit (node:events:329:20)
at addChunk (node:internal/streams/readable:304:12)
at readableAddChunk (node:internal/streams/readable:279:9)
at Socket.Readable.push (node:internal/streams/readable:218:10) {
code: 'ER_PARSE_ERROR',
errno: 1064,
sqlState: '42000',
sqlMessage: "You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '-ID, File_Name) VALUES ('112', 'test2')' at line 1",
sql: "INSERT INTO files (File-ID, File_Name) VALUES ('112', 'test2')"
}
Seems that a column name in you import files is not valid as you see at the end of you error message you have
INSERT INTO files (File-ID, File_Name) VALUES ('112', 'test2')
The column name File-ID should be changed (the minus sign in mysql is used for math and mean column FIle - column ID )
or using backtics
INSERT INTO files (`File-ID`, File_Name) VALUES ('112', 'test2')
or avoidng the minus sign
INSERT INTO files (File_ID, File_Name) VALUES ('112', 'test2')
try edit the file and change the name properly

Uploading a file using Node without changing to a new page

I've been following some tutorials on how to upload a file using node and I've had success in actually uploading the file (I've primarily used https://www.geeksforgeeks.org/file-uploading-in-node-js/). However, every time it uploads the file, it changes to a new page. Is there a way to stay on the same page after uploading the photo, or do I have to create an HTML file with the same name with the same HTML as before the upload? The working code is below:
const express = require("express")
const path = require("path")
const multer = require("multer")
const app = express()
app.use(express.static(__dirname + '/public'));
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, "uploads")
},
filename: function (req, file, cb) {
cb(null, file.fieldname + "-" + Date.now()+".jpg")
}
})
var upload = multer({
storage: storage,
fileFilter: function (req, file, cb){
var filetypes = /jpeg|jpg|png/;
var mimetype = filetypes.test(file.mimetype);
var extname = filetypes.test(path.extname(
file.originalname).toLowerCase());
if (mimetype && extname) {
return cb(null, true);
}
cb("Error: File upload only supports the "
+ "following filetypes - " + filetypes);
}
}).single("myfile");
app.get("/",function(req,res){
res.render("Signup");
})
app.post("/uploadCode",function (req, res, next) {
upload(req,res,function(err) {
if(err) {
res.send(err)
}
else {
res.send("Success, Image uploaded!")
}
})
})
app.listen(8000,function(error) {
if(error) throw error
console.log("Server running on port 8000")
})
If you do the upload from a form where the browser submits the form for you automatically via a submit button, then it will be a browser form POST and the browser will automatically display whatever that POST request returns as the response.
If you, instead, upload form a form with a Javascript Ajax call to do the form POST, then the form response just comes back to your Javascript and nothing happens to the current web page in the browser. Your Javascript can receive that response and then decide what to do with it (if anything).
You've shown your server-side code here, but it's actually the client-side that controls what happens after the response from the upload is received back from the server. So, the changes would have to be made on the client-side to submit your form via Javascript.

Multer NodeJS Extension: Unable to upload an Excel File using Multer

I tried to use multer to upload files onto my server for my NodeJS/Express web application.
I wrote the following function using multer, however, it just displays a page that says [Object Object] and I have no idea why. I am getting no console logs despite inputing them:
This is my route in my controllers: (I have a form that has a file upload tag on one of my pages)
router.post('/upload/file', multer(multConfFile).single('file'), function(req,res){
if (req.fileValidationError) {
console.log("This was a valid error");
return res.send(req.fileValidationError);
}
else if (!req.file) {
console.log("this error occured");
return res.send('Please select a file to upload');
}
else if (err instanceof multer.MulterError) {
console.log("Multer error");
return res.send(err);
}
else{
console.log(req.file)
res.redirect('back');
}
This is my multer config to allow uploads of Excel files:
const multConfFile = {
storage: multer.diskStorage({
destination: function(req,file,callback){
callback(null, '../models/assets/files');
},
filename: function(req, file, callback){
const ext = file.mimetype.split('/')[1];
console.log(ext);
callback(null, file.fieldname + ext);
}
}),
fileFilter: function(req, file, next){
if(!file){
next();
}
if(!file.originalname.match(/\.(xlsx|xlsb|csv|xlsm)$/)){
next(null, true);
}
else{
next({message: "File not supported"});
}
}
};
I am not certain why this is not working? Any suggestions? Could it be a problem with excel file uploads?

Get File from POST request body NodeJS & Angular

I am working on an MEAN Stack application and I am trying to manage a form that allows users to upload a file when they submit. It appears to be working on the client side, however when I send the post request from the client and inspect the request body the file is an empty object. It is just a small .docx file so it should be fine size-wise. But I do not understand why nothing is properly received since the request goes through with out error. I was under the impression that files could be sent this way.
Am I missing something?
code from angular service
sendApplcation(data : any): Observable <any>
{
return this.http.post(this.url+ '/careers/api/application', data);
}
nodejs code
router.post("/api/application", (req, res) => {
const application = req.body;
console.log(req.body.file);
let email = {
to: `${req.body.email}`,
from: "Careers#TrueLogistics.ca",
subject: "Application Recieved",
text: JSON.stringify(req.body),
html: `<p> ${JSON.stringify(req.body)} </p>`,
};
mailer.sendMail(email, (err, res) => {
if (err) {
console.log(err);
}
});
email.to = "mjayfalconi#gmail.com";
mailer.sendMail(email, (err, res) => {
if (err) {
console.log(err);
}
});
res.json("Applcation Submitted Successfully!");
});
Check out the multer package on npm.
File upload works a bit differently than the normal request.
You will also set enctype to multipart at the front end.
Furthermore, I see you are using nodemailer to send the file as an attachement. Read the documentation about the attachment. You don't send the file that way.
//Dependencies
const multer = require('multer');
//Multer DiskStorage Config
const diskStorage = multer.diskStorage(
{ destination: 'assets/profile_upload'} );
//Create Multer Instance
const upload = multer({ storage: diskStorage });
//File upload
//or app.post()
router.post('/upload-file', upload.single('file'), (req, res) => {
//The file
console.log(req.file)
;});
//Your code:
app.post('/upload', (req, res) => { ... try doing app.post('/upload' ,upload.single('file'),
Also check out this post: https://stackoverflow.com/a/61341352/9662626
Sorry for the bad formatting. I only have access to my phone at the moment.

Express file upload and view

I am using express-fileupload to upload the images. The images are saved in my local directory. I want to insert the name of the file to the mongodb if possible. Finally I want the image to be displayed in my frontend.
function insertRecord(req,res){
if(req.files){
const file=req.files.filename
filename=file.name
file.mv("./upload"+filename,function(err){
if(err)
console.log(err)
})
}
const user=new User()
user.name=req.body.name
user.address=req.body.address
user.email=req.body.email
user.mobile=req.body.mobile
user.filename=req.body.filename
user.save((err,docs)=>{
if(!err){
res.redirect('/user/list')
}
else {
if (err.name == 'ValidationError') {
handleValidationError(err, req.body);
res.render("./users/addOrEdit", {
viewTitle: "Insert User",
user: req.body
});
}
else
console.log('Error during record insertion : ' + err);
}
});
}
I am not sure whether the way to insert the name of the file to the mongodb is correct or not. Anyway, that is optional but I am not understanding how can I display the uploaded images which are present in the local directory.
I tried to save the image as base64 but the record is not saved to the database now.
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, 'uploads/')
},
filename: function (req, file, cb) {
cb(null, file.fieldname + '-' + Date.now())
}
})
var upload = multer({ storage: storage })
router.post('/',upload.single('myImage'),function(req,res){
if (req.body._id == '')
insertRecord(req, res);
else
updateRecord(req, res);
})
function insertRecord(req,res){
var img = fs.readFileSync(req.file.path);
var encode_image = img.toString('base64');
var finalImg = {
contentType: req.file.mimetype,
image: new Buffer(encode_image, 'base64')
};
const user=new User()
user.name=req.body.name
user.address=req.body.address
user.email=req.body.email
user.mobile=req.body.mobile
user.save(finalImg,(err,docs)=>{
if(!err){
res.redirect('/user/list')
}
else {
if (err.name == 'ValidationError') {
handleValidationError(err, req.body);
res.render("./users/addOrEdit", {
viewTitle: "Insert User",
user: req.body
});
}
else
console.log('Error during record insertion : ' + err);
}
});
}
Edit: I think there is a problem in the code: it should be `'./upload/'+filename' not without the second slash.
In order to show the images, you have to open a static route in Express. Example: app.use('/images', express.static(PATH)). Then you can, in the frontend, call it as <img src="URL/images/FILENAME" />
From your code, it is not possible to understand what kind of data you are sending to the server. As far as I understand, you're trying mv the string filename. In order to transfer files (such as images), you should have form-data instead of JSON data or you should encode the image file into Base64 to transfer it as text (not the filename, the whole file).
Check Multer out for this kind of job. It is described well in the README.md. Apart from that, until you submit the form, the image won't be available in the front-end. If you want to preview the image before uploading it's a separate process which you can learn more in here.

Categories

Resources