Why node app crashes when req.files is null? - node.js

I have a frontend app(react) where the user can edit the product like price, description, delete images and add images.
The problem occurs when the user does not want to add new images.
Then on the backend(nodejs) req.files.newImages as I named it is null
and the backend crashes.
When I add one image or more everything works as it should because req.files.newImages has a value.
How to cover the case when the user does not want to add new images and prevent the app from crashing
I use express-fileupload and I use axios and put method to send data.
routes.put("/edit-product", (req, res) => {
console.log(req.files.newImages) // - result app crashed
}
Error in console: TypeError: Cannot read property 'newImages' of null;

You can simply check if there are any files like this:
if (req.files) {
// do something
}
Alternatively you can use optional chaining:
console.log(req.files?.newImages); // will log "undefined"

first check if it comes with console.log(req.files) with another name, if not, make sure you send it as "multipart" on the front-end side

Related

Cannot read properties of undefined (reading 'filename') nodejs --multer

I'm currently trying to make the user can edit their profile picture, I'm using nodejs, react & multer for that. On the other hand I receive an error when I send my form, I show you my code I hope you can help me.
Sending the form gives me no error when I put a req.body.file in my edit function but then the image of my profile is undefined,
I also tried req.file[0].filename, which doesn't work either.
I would like that when the user uploads an image it is downloaded in my images folder and that it is also displayed on the user's profile
I thank you in advance
when doing a put request you are sending your data in JSON not in form data. you need to do something like this
const onSubmit = () => {
const formData = new FormData();
formData.append("firstName", firstName);
....
formData.append("avatar", avatar);
also FileReader.readAsDataURL return string but multer needs value of type File, so we need to directly store event.target.files[0] inside state so that multer can read it.
make sure you have express middleware
app.use(express.json());
not but the least upload.single("avatar") it should be the name of variable
hope these changes help you.
I didn't see your implementation for React updateUser, but looks like you are using the key avatar when uploading a file but accessing it via image key.
Also just use file Blob from HTMLInput
const handleImgUpload = (e) => setAvatar(e.target.files[0])
Try to change your router to
router.put('/update/:id', requiresAuth, upload.single('avatar'), updateUser)
and make sure you submit the form with Content-Type header multipart/form-data

Why can't I set two different states from the same response object?

I'm getting an S3 signed URL response back to my client from my NodeJS server which handles communication with S3. I need the signed URL to upload images directly to S3 from my front end, and I need the image URL to display it from the S3 bucket. However I can't seem to set two different states with the same response object without getting a 403(Forbidden) error. I can set one state just fine and use it, but as soon as I try and set two using the same response object, it doesn't like it.
403Error
useEffect(() => {
async function getURL() { try {
await axios.get("imageRouter/S3Url").then((response) => {
setImageUrl(response.data.url.split("?")[0]);
setSignedUrl(response.data.url);
});} catch (error) {
console.log(error);
}}
getURL();},
[selectedFile]);
selectedFile is not a dependency of useEffect, the two dependencies are: setImageUrl and setSignedUrl and you should cache them so they won't change every time the state changes (using React.memo).
You should check the signed URL that is returned, by default the expiration is 15 minutes IIRC, so if you generate it once and use it multiple times you should make sure that it's not expired and if so - regenerate it. This can be checked by looking at the Expires parameter which shows up as a query param on the signed-url. We can use: https://www.epochconverter.com/ to translate it to a timestamp in a more readable format

Delete multiple array // "route doesn't exist"

I tried to delete the array of multiple elements but I guess I do something wrong.
My app looks like this picture
So, when I press on mass delete I get an error that the route doesn't exist (picture)
I think it's because in my node route look like
import express from "express";
const router = express.Router();
import {
createProduct,
getAllProducts,
deleteProduct,
} from "../controllers/productController.js";
router.route("/createProduct").post(createProduct);
router.route("/").get(getAllProducts);
router.route("/:id").delete(deleteProduct);
export default router;
I tried in postman and it's successful, I think because I pass by id, but now in my state I have selected items array and its a bunch of ids picture
So, how in route write that it's an array?
Thanks in advance
The error is because the only delete endpoint that exists is the one where you pass an id as the parameter router.route("/:id").delete(deleteProduct);, so when you target localhost:5000/api/v1/ with a HTTP DELETE it throws a 404 error.
For multiple deletion you can maybe create a new route say:
router.route("/deleteMassProducts").delete(deleteMassProducts);
you can then send the array of selected items in the request body and then delete them with whatever logic you prefer. You can also accomplish this without changing anything on the backend, just loop through the selected items and target the delete route with the :id parameter multiple times for each of the selected items id.

Good practice to handle useless response in express js/nodejs?

Am using express js on node for my api service ! In which am using sequelize for query handling purposes !
So in some usecase like creating record, or updating record its simply returning "1" or sometimes nothing !
In this case , am just using
res.sendStatus(200);
or sometimes
res.send("success");
Is there any better way or this is the correct way to handle ? Or should in need .end() in order to end the process ??
which is a good way to handle these kind of useless responses which we dont need to send back ?
This is where Status 204 comes in to play: https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#2xx_success
It states: everything is OK (like in 200), but there is simple no need to send a body.
Using express, it's just as simple as: res.sendStatus(204)
Usually a json is send back to the client with different information in it that lets the client-side know that the operation that they request through the api is successfull or failed. for e.g. here, you can define a standard json response like this
//in case of success of the request
{
requestStatus: 1,
...other data if you want to like new Id of the created data/updated data or info about it if you want or depending upon use case
}
or
// in case of failure of the request
{
requestStatus: 0,
...other data if you want to like reason for failure, error message or depending upon your use case
}
Just add this line of code, should be fine:
//For all bad endpoints
app.use('*', (req, res) => {
res.status(404).json({ msg: 'Not a good endpoint, why are you here? Go play FIFA.'})
})
If you want you can generate an error HTML file, but since it's back-end, JSON format is strongly suggested. You can also add success: false for more clarity.

how to handle multiple conncurrency request in node.js

I am trying to upload multiple images at simultaneously. in server side i have to
create one unique folder for to keep that images .so how to make wait request until one request complete and send response to client. i have tried this one but when i send response i am getting this error Can't set headers after they are sent.so suggest me good solution . i am waiting for urs reply.
when i upload five images , in server side i have to check whether folder is already exist or not. if it is not exist i have to create new folder for that five images and then i have to check that folder reference is already exist or not in mongodb.if it is not exist i have to store that folder reference in mongodb.and then i have to send response to client. but here when i upload five image, five request is going to server so request is doing that terms before complete one request so same folder reference is storing and also it is creating five folder for five image.
function myMiddleware(req, res, next)
{
console.info("inside myMiddleware");
var handler = function()
{
console.info("middleware redundant. ActionDone, calling next");
next();
};
EventManager.once("finished",handler);
if (actionDone !== "working")
{
actionDone = "working";
function doneWaiting(){
// console.log("finished");
actionDone = "finished";
EventManager.emit( "finished" );
}
setTimeout(doneWaiting, 500);
}
I think that what you need here is implementing a lock on the function that checks/creates the folder and does the database check/create.
Take a look at this article to see an example

Resources