Unable to upload Files Using Multer React Js And Express - node.js

Attaching Documents Pic
As shown in the pic i am attaching my documents.
onDrop: (acceptedFiles, rejectedFiles) => {
if (rejectedFiles.length) {
toast.error('You can upload images , Words and Excel files !.')
} else {
console.log(acceptedFiles)
setFiles([...files, ...acceptedFiles.map(file => Object.assign(file))])
}
}
axios.post('http://localhost:5000/AddEmployee', {
user, employeeDocuments : user[2].documents
})
.then(res => {
console.log(res)
})
.catch(err => {
console.log(err)
})
I am storing all test documents in the employeedocuments array and then i am sending post request to backend.
employeeDocuments array in console log view
Here i am console log the employeeDocuments array it is looking fine.
enter code here
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, "./public/uploads");
},
filename: function (req, file, cb) {
cb(null, file.fieldname + "-" + Date.now() + path.extname(file.originalname));
},
});
var upload = multer({ storage: storage });
var uploadMultiple = upload.fields([{ name: 'employeeDocuments', maxCount: 10 }])
This is my backend multer code to upload files i have used the name employeeDocuments to upload files but multer is not uploading these files.Rather i used postman and it was working fine. But when i upload these files using react by post request these files not get uploaded.

I faced a similar issue and I was able to fix it by modifying my axios post request to sending Form Data:
const formData = new FormData()
formData.append('imagePath', image)
The have the upload in the post like this: router.post("/AddEmployee",upload, async (req, res)
And store it in the DB as a path using req.file.path
Sorry if its a bit confusing but this is everything I have in my code and its fully working

Related

Multer's path after uploading a file provides the full relative path in my machine

So I'm new to backend and node, and have been working on an app that should also support an image file upload when creating a new item.
I had issues at first getting this error ENOENT: no such file or directory but after following the answers here (I'm using a windows machine and was following a tutorial on a Mac)
ENOENT: no such file or directory .?
I've switched to using the __dirname together with path and I have no such error anymore.
What I do face now is another issue:
When I ask for the file.path, it is no longer relative like ./uploads but instead it is the full path on my computer
C:\Users\myuser\Documents\Coding\travel-market\api\src\uploads\2022-12-05T12-39-35.924Z-Screenshot 2022-11-02 193712.png
So when I pull that new item and try to render the image it doesn't show. Also I get this error Not allowed to load local resource.
Is that ok and would work just fine once the api is actually hosted on a server? Or is there a different way of doing things that would allow me to also view the image while I'm developing locally?
This is my entire code for saving right now:
const storage = multer.diskStorage({
destination: function(req, file, cb) {
cb(null, path.join(__dirname, "..", "uploads"));
},
filename: function(req, file, cb) {
const uniqueName =
new Date().toISOString().replace(/:/g, "-") + "-" + file.originalname;
cb(null, uniqueName);
},
});
const fileFilter = function(req, file, cb) {
if (!file.originalname.match(/\.(jpg|jpeg|png)$/)) {
return cb(new Error("Please upload an image file"));
}
cb(undefined, true);
};
const upload = multer({
storage,
limits: {
fileSize: 1024 * 1024 * 5, // This number is in bytes, so this is 5mb
},
fileFilter,
});
// Post a new plan
router.post("/plans", auth, upload.single("plan_image"), async(req, res) => {
console.log("this is the file", req.file);
const details = JSON.parse(req.body.details);
console.log("this is the body", details);
const plan = new Plan({
...details,
image: req.file.path,
author: req.user._id,
});
try {
await plan.save();
res.status(201).send(plan);
} catch (e) {
console.log("failed to save", e);
res.status(400).send(e);
}
});

Save image url to database after upload

I upload an image from a react native expo app.
In the back end, I have this code :
const storage = multer.diskStorage({
destination: (req, file, callback) => {
callback(null, "avatars");
},
filename: (req, file, callback) => {
let imagePath = Date.now() + path.extname(file.originalname);
callback(null, imagePath);
},
});
const upload = multer({ storage: storage });
app.use("/uploadAvatar", upload.single("avatar"), (req, res) => {
res.status(200).json("Image enregistrée !");
});
It works fine and save the image into a folder.
What I need to do, is to save the image path in the database.
The image is an avatar for a user profile, so I need to add its path to the user table.
Suppose you are storing the image in your middleware:
app.use('/uploadAvatar', upload.single('avatar'), async (req, res) => {
// Assume that you're storing the image with a function,
// in this case you just need to pass the filename into
// your function. This is a pseudocode and is not expected to work
// as it is, so please adjust accordingly.
const result = await storeImage(req.file.filename);
// Return the response as JSON.
res.status(200).json('Image enregistrée!');
});
Basically, you have to inspect the req.file that would be populated after you call the upload.single('avatar') middleware. In this case, we're taking the filename to be stored into the database. You can do any path/file/property manipulations that you might want to do before storing that image, though.
For further information about req.file and what properties it contains, please see the Multer documentation.

Multer super slow upload after recieving post request with images

Hello I'm on a (ReactJs Node Mysql Express) stack, my website has an events tab which the admin could upload to it events.
Each event has a cover photo, inner photos, Title, and a brief text.
So I send this whole form in a single post request (is it good?)
var fileUpload = multer({ storage:storage,
limits:{fileSize:150*1024*1024}
})
const multipleUpload = fileUpload.fields([{ name: 'coverPhoto', maxCount: 1 }, { name: 'innerPhotos', maxCount: 30 }])
const storage = multer.diskStorage({
destination: (req, files, cb) => {
cb(null, '../client/build/imgs/events')
},
filename: (req, files, cb) => {
cb(null, files.originalname)
}
})
The server does recieve the request perfectly but after multer receives the photos it takes so long to move them to the fs and the reverse proxy would send a 524 error that it took so long knowing that the format is webp and the photos are so small in size.
Any idea why is it taking so long?
I tried to move to formidable but I couldn't figure how to retrieve multiple input fields with multiple files in it ( I only succeeded in sending one input not multiple inputs)
Thank you

Send Blob File from html form to express server so it can be uploaded to cloud

So I'm trying to make the html form:
<form action="blahblah" encblah="multipart/form-data" whatever>
Thats not the problem, I need to make that form send the blob to express
app.post('/upload/avatars', async (req, res) => {
const body = req.body;
console.log(req.file);
console.log(body);
res.send(body);
});
So I can access the blob, create a read stream, pipe it to the cloud, and bam, upload the file without downloading anything on the express server it self.
Is that possible?
If yes, please tell me how.
If no, please tell me other alternatives.
On the client we do a basic multi-part form upload. This example is setup for a single image but you could call uploadFile in sequence for each image.
//client.ts
const uploadFile = (file: File | Blob) => {
const formData = new FormData();
formData.append("image", file);
return fetch("/upload", {
method: "post",
body: formData,
});
};
const handleUpload = (event: any) => {
return event.target.files.length ? uploadFile(event.target.files[0]) : null;
};
On the server we can use multer to read the file without persisting it to disk.
//server.js
const express = require("express");
const app = express();
const multer = require("multer");
const upload = multer();
app.post(
"/upload",
upload.fields([{ name: "image", maxCount: 1 }]),
(req, res, next) => {
console.log("/upload", req.files);
if (req.files.image.length) {
const image = req.files.image[0]; // { buffer, originalname, size, ...}
// Pipe the image.buffer where you want.
res.send({ success: true, count: req.files.image.originalname });
} else {
res.send({ success: false, message: "No files sent." });
}
}
);
For larger uploads I recommend socket.io, but this method works for reasonably sized images.
it is possible, but when you have a lot of traffic it would overwhelm your express server (in case you are uploading videos or big files ) but if it's for uploading small images (profile image, etc...) you're fine. either way you can use Multer npm
I'd recommend using client-side uploading on ex: s3-bucket, etc..., which returned a link, and therefore using that link.

Track progress for image upload using multer, express and multer-s3 for NodeJS

I'm trying to upload images to AWS S3 using multer-s3. Everything works fine (i.e. uploading video, images and files) but it's incomplete. I have no idea how to track the progress or percentage of the upload.
My code for multer is treated as a middleware like this
const multer = require('multer');
const AWS = require('aws-sdk');
const multerS3 = require('multer-s3');
var s3 = new AWS.S3();
const s3Storage = multerS3({
s3 : s3,
bucket : 'app-bucket',
acl : 'public-read',
key : function (req, file, callback) {
callback(null, file.originalname);
}
});
module.exports.s3Upload = multer({ storage: s3Storage });
Then I will attached the middleware to my route like this:
router.route('/image/upload').get(uploadController.getUploadImageController)
.post(middleware.s3Upload.single('myImage'),
uploadController.postUploadPhotoToAlbumController );
Then on my controller, is a simple post request that will save the path to database:
module.exports.postUploadPhotoToAlbumController = (req, res) => {
let query = Images.findById({ _id: req.params.id });
query.exec((err, images) => {
if(err){
return res.status(500).send({success: false, error: err, message: 'Something went wrong.'});
} if(!images){
return res.status(200).send({success: false, message: 'That image does not exist to your album.'});
}
images.image = !!req.file ? AwsS3PublicURL.setAwsPublicUrlSingle(req) : null;
images.save(err => {
if(err){
return res.status(500).send({success:false, error: err, message: 'Something went wrong.'});
}
req.flash('message', 'Your image was successfully uploaded.');
res.redirect('/album/photos');
});
});
}
The AwsS3PublicURL.setAwsPublicUrlSingle is a a path to my
AmazonS3Bucket set to public.
My problem is I don't know how to properly track the progress or percentage of progress of my upload and display on frontend or in console. Thank you in advance if anyone knows the answer.

Resources