i use multer package with node and react and i send a file to node js backend, but always its undefined..
This is React
<div className="file-field input-field">
<div className="btn">
<span>File</span>
<input
type="file"
name="image"
id="image"
onChange={changedImageUpload}
/>
</div>
<div className="file-path-wrapper">
<input className="file-path validate" />
</div>
</div>
and that is onChange file handling method in there i just get first console.log but second and third is not printed
const changedImageUpload = (e) => {
const file = e.target.files[0];
const formData = new FormData();
formData.append("image", file);
console.log(formData, file);
try {
const config = {
Headers: {
"Content-Type": "multipart/form-data",
},
};
axios
.post("/uploads", formData, config)
.then((res) => {
console.log(res.data);
})
.catch((err) => {
console.log(err);
});
} catch (err) {
console.log(err);
}
};
and its Node codes and multer configure
import express from "express";
import multer from "multer";
const route = express.Router();
const storage = multer.diskStorage({
destination: (req, file, cb) => {
cb(null, "images");
},
filename: (req, file, cb) => {
cb(
null,
new Date().toISOString().replace(/[\/\\:]/g, "_") + file.originalname
);
},
});
const multerFilter = (req, file, cb) => {
if (
file.mimetype === "image/png" ||
file.mimetype === "image/jpg" ||
file.mimetype === "image/jpeg"
) {
cb(null, true);
} else {
cb(null, false);
}
};
const upload = multer({ storage: storage, fileFilter: multerFilter });
route.post("/uploads", upload.single("image"), (req, res) => {
try {
// res.send(`/${req.file.path}`);
console.log(req.file);
} catch (err) {
console.log(err);
}
});
and import in app.js
import uploadRoutes from "./Routes/uploadRoutes.js";
app.use(uploadRoutes);
const __dirname = path.resolve();
app.use("/images", express.static(path.join(__dirname, "/images")));
so at printing formData i always get empty object, and if i print req.file i get an undefined in node js
Your filter function is wrong. You are comparing the mimeType to things like jpg which isn't a real MIME type, so your files are always filtered out.
You need to compare to image/png and image/jpeg instead.
Related
I have array with buffer files. I have been trying upload buffers to express server using multer for whole day.
Problem is my files pass by req.body.image. But multer finds files from req.files. Multer can't found files and alerted error. How fix this problem?
Front End code:
let UserPhoto = ["data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/4gIoSUNDX1BST0ZJTEUAAQEAAAIYAAAAAAQwAABtbnRyUkdCIFhZWiAAAAAAAAAAAAAAAABhY3NwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAA9tYAAQAAAADTLQAAAAAAAAAAAAAAAAAA"];
let formData = new FormData();
for (let i = 0; i < userPhoto.length; i++) {
formData.append("files", userPhoto[i]);
}
axios
.post(`v0/photo/${id}/User`, formData, {
headers: { "Content-Type": "multipart/form-data" },
})
.then((result) => {
console.log(result);
})
.catch((error) => {
console.log(error);
}
Back End code:
const fileFilter = (req, file, cb) => {
if (file.mimetype.substr(0, 6) === "image/") {
cb(null, true);
} else cb(new ErrorCatcher("Зөвхөн зураг upload хийнэ үү.", 400), false);
};
const storage = multer.diskStorage({
destination: (req, file, cb) => {
cb(null, director);
},
filename: (req, file, cb) => {
cb(null, Date.now() + "." + file.mimetype.split("/")[1]);
},
});
const upload = multer({
storage: storage,
limits: { fileSize: process.env.IMAGE_MAX_SIZE },
fileFilter: fileFilter,
});
//authorize,
// permission("user", "operator", "manager", "admin"),
router
.route("/:objectId/:objectType")
.post(upload.array("files", 8), createImageConnect);
I was using formData. Result was same.
I simply have this on my server
const storage = multer.diskStorage({
destination: "public/something/images",
filename: function (req, file, cb) {
console.log(file, "file?");
cb(
null,
file.fieldname + "-" + Date.now() + path.extname(file.originalname)
);
},
});
var upload = multer({ storage: storage });
app.post("/upload", upload.single("file"), (req, res) => {
console.log(req.file, "req?"); // this is undefined?
console.log(req.files.File, "req?"); // this is the correct file. why does the line above not work?
res.json({ file: req.file });
});
on my frontend I have:
<input type="file" name="file" onChange={changeHandler} />
public/something/images does get created but the image is not inside it, why is this happening?
request:
const endpoint = () => {
const formData = new FormData();
formData.append("File", selectedFile);
fetch("http://localhost:4000/upload", {
method: "POST",
body: formData,
})
.then((r) => r.json())
.then((a) => console.log(a));
};
I am able to upload a single file using multer. But when it comes to multiple files it won't work anymore and no file is caught by multer.
I send files through formData.append(). But it only uploads single file
Vue component
const formData = new FormData();
formData.append("productImg", this.imgFile);
this.$store.dispatch(POST_PRODUCT_IMAGE, formData)
.then((response) => {
console.log(response.data);
})
.catch(error => {
console.log(error);
})
Server file
const uploadPath = path.join(__dirname, '/../../public/uploads');
var storage = multer.diskStorage({
destination: (req, file, callback) => {
callback(null, uploadPath + "/garbage/productImg");
},
filename: (req, file, callback) => {
var newName = Date.now() + "_" + file.originalname;
callback(null, newName);
}
});
const upload = multer({
storage: storage
});
productRouter.post('/uploadProductImage', upload.any(), async (req, res) => { // Some Code })
I did also
productRouter.post('/uploadProductImage', array('productImg[]', 6), async (req, res) => { // Some Code })
I want to upload multiple files at a time to my specified folder.
Finally i found a solution which is very silly though.
In Vue component file i just use a loop before add in formData. Like this.
Vue Component
const formData = new FormData();
// formData.append("productImg", this.imgFile); // OLD ONE
for (let index = 0; index < this.imgFile.length; index++) { //NEW ONE
let file = this.imgFile[index];
formData.append("productImg["+index+"]", file);
}
this.$store.dispatch(POST_PRODUCT_IMAGE, formData)
.then((response) => {
console.log(response.data);
})
.catch(error => {
console.log(error);
})
I am trying to upload a single file, and store it in a folder in my app directory. On the frontend, I am successfully selecting a file and adding it to the state of the Uploader component. When I make the POST request to the Node route with Axios, I am getting undefined in the request body.
Here is the component:
import React, { Component } from 'react';
import axios from 'axios';
export default class SandboxGet extends Component {
constructor(props) {
super(props);
this.state = {
file: null
};
}
fileSelectHandler = event => {
const file = event.target.files[0];
this.setState({ file: file.name });
};
fileUploadHandler = () => {
const data = new FormData();
data.append('file', this.state.file);
console.log(data);
axios
.post('http://localhost:4000/upload/', this.state.file, {
// receive two parameter endpoint url ,form data
})
.then(res => {
// then print response status
console.log(res.statusText);
});
};
render() {
return (
<div className="uploaderContainer">
<div className="uploadInput">
<i className="fas fa-upload" />
<button className="uploadBtn">Select Files</button>
<input type="file" name="file" onChange={this.fileSelectHandler} />
<div className="fileName">{this.state.fileName}</div>
</div>
<button className="uploadFile" onClick={this.fileUploadHandler}>
Upload!
</button>
</div>
);
}
}
Here is the Node server:
const express = require('express');
const app = express();
const multer = require('multer');
const cors = require('cors');
app.use(cors());
const storage = multer.diskStorage({
destination: (req, file, cb) => {
cb(null, '/storage');
},
filename: (req, file, cb) => {
cb(null, Date.now() + '-' + file.originalname);
}
});
const upload = multer({ storage: storage }).single('file');
app.post('/upload', (req, res) => {
console.log(req.file); // => returns nothing
console.log(req.body; // => returns nothing
upload(req, res, function(err) {
if (err instanceof multer.MulterError) {
return res.status(500).json(err);
} else if (err) {
return res.status(500).json(err);
}
return res.status(200).send(req.file);
});
});
app.listen(4000, function() {
console.log('App running on port 3000');
});
I feel like I am getting close, but I am missing a big piece of the puzzle.
You are sending the this.state.file. You need to send the FormData.
In your case it is .post('http://localhost:4000/upload/', data)
Also, you need to send the multipart/form-data header.
const headers = {
'content-type': 'multipart/form-data'
}
Then,
axios.post('http://localhost:4000/upload/', data, {headers});
I'm trying to upload multiple images using Multer. It all works as expected except that only one file is being uploaded (the last file selected).
HTML
<form class='new-project' action='/projects' method='POST' enctype="multipart/form-data">
<label for='file'>Select your image:</label>
<input type='file' multiple='multiple' accept='image/*' name='uploadedImages' id='file' />
<span class='hint'>Supported files: jpg, jpeg, png.</span>
<button type='submit'>upload</button>
</form>
JS
//Define where project photos will be stored
var storage = multer.diskStorage({
destination: function (request, file, callback) {
callback(null, './public/uploads');
},
filename: function (request, file, callback) {
console.log(file);
callback(null, file.originalname)
}
});
// Function to upload project images
var upload = multer({storage: storage}).any('uploadedImages');
// add new photos to the DB
app.post('/projects', function(req, res){
upload(req, res, function(err){
if(err){
console.log(err);
return;
}
console.log(req.files);
res.end('Your files uploaded.');
console.log('Yep yep!');
});
});
I get the feeling I'm missing something obvious...
EDIT
Code I tried following Syed's help:
HTML
<label for='file'>Select your image:</label>
<input type='file' accept='image/*' name='uploadedImages' multiple/>
<span class='hint'>Supported files: jpg, jpeg, png.</span>
<input type="submit" value="uploading_img">
JS
multer = require('multer'),
var upload = multer();
app.post('/projects', upload.array('uploadedImages', 10), function(req, res, err) {
if (err) {
console.log('error');
console.log(err);
}
var file = req.files;
res.end();
console.log(req.files);
});
Uploading multiple files with Multer
NodeJs Code
Set require files and Storage
const express = require('express');
const multer = require('multer');
const path = require('path');
const app = express();
const port = 3000
const storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, path.join(__dirname, './images/'))
},
filename: function (req, file, cb) {
cb(null, file.fieldname + '-' + Date.now() + file.originalname.match(/\..*$/)[0])
}
});
Set upload file limit or validataion
const multi_upload = multer({
storage,
limits: { fileSize: 1 * 1024 * 1024 }, // 1MB
fileFilter: (req, file, cb) => {
if (file.mimetype == "image/png" || file.mimetype == "image/jpg" || file.mimetype == "image/jpeg") {
cb(null, true);
} else {
cb(null, false);
const err = new Error('Only .png, .jpg and .jpeg format allowed!')
err.name = 'ExtensionError'
return cb(err);
}
},
}).array('uploadedImages', 2)
Create the main route for uploading
app.post('/projects', (req, res) => {
multi_upload(req, res, function (err) {
if (err instanceof multer.MulterError) {
// A Multer error occurred when uploading.
res.status(500).send({ error: { message: `Multer uploading error: ${err.message}` } }).end();
return;
} else if (err) {
// An unknown error occurred when uploading.
if (err.name == 'ExtensionError') {
res.status(413).send({ error: { message: err.message } }).end();
} else {
res.status(500).send({ error: { message: `unknown uploading error: ${err.message}` } }).end();
}
return;
}
// Everything went fine.
// show file `req.files`
// show body `req.body`
res.status(200).end('Your files uploaded.');
})
});
Listen port
app.listen(port, () => {
console.log(`Example app listening at http://localhost:${port}`)
});
HTML code
<form id="form_el" class='new-project' action='/projects' method='POST' enctype="multipart/form-data">
<label for='file'>Select your image:</label>
<input type='file' multiple='multiple' accept='image/*' name='uploadedImages' id='file' />
<span class='hint'>Supported files: jpg, jpeg, png.</span>
<button type='submit'>upload</button>
</form>
JAVASCRIPT CODE
form_el.addEventListener('submit', async function (e) {
const files = e.target.uploadedImages.files;
if (files.length != 0) {
for (const single_file of files) {
data.append('uploadedImages', single_file)
}
}
});
const submit_data_fetch = await fetch('/projects', {
method: 'POST',
body: data
});
Here you go for this example:
var multer = require('multer');
var upload = multer();
router.post('/projects', upload.array('uploadedImages', 10), function(req, res) {
var file = req.files;
res.end();
});
<form action="/projects" method="post" enctype="multipart/form-data">
<input type="file" name="uploadedImages" value="uploading_img" multiple>
<input type="submit" value="uploading_img">
</form>
Visit for more info about Multer.
My guess is that for each file that you want to upload, you reclick:
<input type='file' multiple='multiple' accept='image/*' name='uploadedImages' id='file' />
If you do this, then only the last file selected will be uploaded, as you overwrite the previous selected files.
To upload multiple files, you have to select them all at once in the file picker.