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.
Related
I have an express server. When the user goes to make a post request for the profiel. They submit a profile picture. I am trying to use multer to grab that photo/image that is being sent and store it in a folder on the backend directory.
I setup multer but for some reason it is not saving any of the photos that I want it to save locally so that I can retrieve it. How can I fix this issue. Does anyone have an idea on how to go about this.
controller:
const Profile = require("../../models/UserModels/Profiles.js")
const User = require('../../models/UserModels/Users.js')
const multer = require('multer')
const storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, '../../client/images/profile/')
},
filename: function (req, file, cb) {
const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1E9)
cb(null, file.fieldname + '-' + uniqueSuffix)
}
})
const upload = multer({ storage: storage })
...
post:(req, res) => {
console.log(req.body)
console.log(req.files)
upload.single(req.files.profile_pic.name) <----------------
let body = req.body
Profile.create({
profile_pic: req.files.profile_pic.name,
f_name: body.f_name,
l_name: body.l_name,
bio: body.bio,
location: body.location,
sm_facebook: body.sm_facebook,
sm_instagram: body.sm_instagram,
sm_twitter: body.sm_twitter,
sm_website: body.sm_website,
followers: body.followers,
following: body.following,
photos: body.photos,
downloads: body.downloads,
edits: body.edits,
userId: body.userId
})
.then((data) => {
res.send(data).status(200)
})
.catch((err) => {
console.error(err)
res.send(err).status(400)
})
},
Here is the direcory for this backend:
-----------update---------------
this is the react axios request from the frontend:
function createProfile(userId){
let data = new FormData()
data.append('f_name', firstName)
data.append('l_name', lastName)
data.append('bio', bio)
data.append('location', location)
data.append('sm_facebook', facebook)
data.append('sm_instagram', instagram)
data.append('sm_twitter', twitter)
data.append('sm_website', website)
data.append('followers', 0)
data.append('following', 0)
data.append('photos', 0)
data.append('edits', 0)
data.append('downloads', 0)
data.append('userId', userId)
data.append('profile_pic', profilePicture)
console.log(data)
axios({
method: "post",
url: "/api/profile/",
data: data,
headers: { "Content-Type": "multipart/form-data" },
})
.then((data) => {
return(<Navigate to='/' />)
})
.catch((err) => {
console.error(err)
})
}
You have to specify the storage path for multer as if you were located on the root folder of the project.
So instead of using '../../client/images/profile/' as storage path, you should use: './backend/client/images/profile'.
You'll code should end up as follows:
const multer = require('multer')
const storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, './backend/client/images/profile')
},
filename: function (req, file, cb) {
const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1E9)
cb(null, file.fieldname + '-' + uniqueSuffix)
}
})
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 need to post an array of images and a single image for product preview.
Here my multer settings
const multer = require('multer');
// Multer settings
const storage = multer.diskStorage({
destination: function(req, file, cb) {
cb(null, './uploads/');
},
filename: function(req, file, cb) {
cb(null, file.originalname);
}
});
const fileFilter = (req, file, cb) => {
// reject a file
if (file.mimetype === 'image/jpeg' || file.mimetype === 'image/png') {
cb(null, true);
} else {
cb(null, false);
}
};
const upload = multer({
storage: storage,
fileFilter: fileFilter
});
const multerSettings = upload.fields([{ name: 'thumb', maxCount: 1 }, { name: 'images', maxCount: 8 }]);
module.exports = multerSettings;
My model for posting data. I am using MongoDB
thumb: {
url: String
},
images: [{url: String}]
Client part
const fd = new FormData();
const { images, thumb } = state.details;
fd.append('thumb', thumb);
fd.append('images', images);
await this.$axios.post('/product', fd);
Images are an array of files [File, File, File], and for some reason, req.files['images'] is undefined on the server, but thumb works properly. And when I am sending the same data via postman all works as expected. In the browser in header preview i see the following data
thumb: (binary)
images: [{},{},{}]
Maybe images should be an array of binary data?
And when sending a single file like this
fd.append('images', images[0]);
req.files['images'] its work properly. I need somehow modify my array on the client. By i have no idea what i should do.
I would be grateful for any tips
The solution is pretty simple.
const fd = new FormData();
const { images, thumb } = state.details;
fd.append('thumb', thumb);;
for(let i = 0; i < images.length; i++) {
fd.append('images', images[i]);
}
await this.$axios.post('/product', fd);
const files = new FormData();
files.append('files', data);
const res = await httpApi.post('/user/upload', files, {headers: { 'Content-Type': 'multipart/form-data'}});
This works! :)
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 just can't figured whats wrong why my codes below. I try to upload multiple files.
The problem is that i had an "UNEXPECTED FIELD"
I can make it to upload single file just fine, but I can't make it upload multiple files. So what's wrong here?
html
<input id="file" type="file" class="form-control" placeholder="Imagen" name="image" multiple>
component.js
var payload = new FormData();
var files = $('#file')[0].files
for (key in $scope.producto) {
payload.append(key, $scope.producto[key])
console.log($scope.producto[key])
}
if (files.length > 0) {
for (var i = 0; i < files.length; i++) {
var file = files[i];
console.log(file)
console.log(files.length)
payload.append('image', file);
}
}
$http.post('http://localhost:5001/api/v1/articles', payload, {
transformRequest: angular.identity,
headers: { "Content-Type": undefined },
}).then(function (response) {
$location.path("/")
})
Here's the server part:
const multer = require('multer')
const storage = multer.diskStorage({
destination : function(req, file, cb){
cb(null, './uploads/');
},
filename : function(req, file, cb){
cb(null, new Date().toISOString() + file.originalname)
}
})
const upload = multer({storage : storage, limits: {
fileSize : 1024 * 1024 * 5
}})
.post('/api/v1/articles/', upload.array('image', 2 ), controllerArticle.postArticles)
controllerArticle.js
function postArticles(req, res) {
// console.log(req.file)
if (req.file) {
const nvo = new articulos({
name: req.body.name,
price: req.body.price,
condition: req.body.condition,
brand: req.body.brand,
productImage: req.file.path
})
nvo.save((err, productStored) => {
if (err) res.status(500)
res.status(200).send({ nvo: productStored })
})
}
}
I have tried so far:
Change upload.array() to upload.any(),and doesn't work..
any help? thanks!
Already solved... The problem was in the controller.
Is req.files not req.file (singular).
if I just need to upload one file it's req.file and to multiple files is req.files.