How to fix/trouble shoot the missing response from nodejs service?

Viewed 98

I am trying to trouble shoot/fix my nodejs upload image api:

My service is being stuck at somewhere.

enter image description here

enter image description here

enter image description here

My service is too simple, just uploading the image by resizing through sharp api in a directory and return the full path of that file.

When I select some image at first time then everything works fine and image upload successfully with a response

but When I try to crop that image after clicking on the image and try to save it (at second time) then nodejs service return following response.

I don't why it is being happened, I tried to debug the service code and It didn't stop at anywhere. Flow has been passed/executed successfully, I didn't catch any exception/error in code.

What can be the issue in it because it still displaying

> Blockquote failed to load response data. no resource with given identifier found

Problem area is in the code of onSaveImage when a server side call is being served/requested. I am using the plugin for image cropping is react-easy-crop. Browser is getting refresh/reload at this line of code

 const jsonRes = await responseMain.json();

I am sharing my nodejs service code as well as reactjs code. please look into it. Thank you.

-----------------package.json of nodejs
{
    "name": "",
    "version": "1.0.0",
    "description": "",
    "main": "index.js",
    "dependencies": {
        "body-parser": "^1.19.0",
        "cors": "^2.8.5",
        "express": "^4.17.1",
        "express-validator": "^6.12.0",
        "handlebars": "^4.7.7",
        "jsonwebtoken": "^8.5.1",
        "mysql": "^2.18.1",
        "nodemailer": "^6.6.1",
        "nodemon": "^2.0.12",
        "sharp": "^0.29.3"
    },
    "devDependencies": {},
    "scripts": {
        "start": "nodemon --inspect index.js",
        "debug": "node --nolazy --inspect-brk=9229 index.js"
    },
    "license": "ISC"
}

------ index.js---------------------------NodeJs
const express = require("express");
const app = express();
const cors = require("cors");
var fs = require("fs");
const fsp = fs.promises;
var path = require("path");
const sharp = require("sharp");

var $pathContentBuilder = path.join(__dirname, "../", "/public/roughdata/uploads/"); 
var $urlpathContentBuilder = "/roughdata/uploads/"; // URL path
app.use(express.json({ limit: "20mb" }));
app.use(cors());
app.use(
    express.urlencoded({
        extended: true,
    })
);
function processImage(image, metadata, filename, isResizeAllow) {
    return new Promise((resolve, reject) => {
        if (isResizeAllow && isResizeAllow === true) {
            // 0.8 MB
            return image
                .resize({
                    width: Math.round(metadata.width / 2),
                    height: Math.round(metadata.height / 2),
                    fit: "cover",
                })
                .toBuffer((err, buf) => {
                    if (err) {
                        console.log("Error occured ", err);
                        return reject(err);
                    } else {
                        return resolve(buf.toString("base64"));
                    }
                });
        } else {
            return image.toBuffer((err, buf) => {
                if (err) {
                    console.log("Error occured ", err);
                    return reject(err);
                } else {
                    return resolve(buf.toString("base64"));
                }
            });
        }
    });
}

app.post("/uploaddetail", async (req, res, next) => {
    const base64Data = req.body.image;
    const filename = req.body.filename;
    let imageResizeResult = "";
    try {
        var inputbuf = Buffer.from(base64Data, "base64"); // Ta-da
        const image = await sharp(inputbuf);
        let metadata = await image.metadata();
        let convertedbase64Data = "";       
        convertedbase64Data = await processImage(image, metadata, filename, false);       
        await fsp.writeFile($pathContentBuilder + filename, convertedbase64Data, "base64");
        let resultResponse = JSON.stringify({
            success: true,
            fullurl: `${$urlpathContentBuilder}${filename}`,
            url: `${filename}`,
            imagename: `${filename}`,
            serverpath: `${$urlpathContentBuilder}`,
        });
        //res.type("json");
        res.status(200).json(resultResponse);
        //res.end();
        //next();
    } catch (e) {
        console.log(e);
        const error = new HttpError(e, 404);
        return next(error);       
    }
});

and following is my reactjs code.

import React, { useState, useEffect, useCallback } from "react";
import { withRouter, useParams, useHistory } from "react-router-dom";
import { Card, Button } from "react-bootstrap";
import Page from "./Page";
import TitleBar from "./TitleBar";
import SingleGalleryRow from "./SingleGalleryRow";
import CenteredPopup from "../common/CenteredPopup";
import { MdDelete, MdOutlineCrop, MdOutlineCircle } from "react-icons/md";
import Cropper from "react-easy-crop";

import getCroppedImg from "../shared/util/cropImage";
import b64toBlob from "../shared/util/blobToImage";

function EditImage({ breadcrumb, pageName, setLoader, showToast }) {
    const [list, setList] = useState([]);
    const history = useHistory();    
    const [umodalShow, setUModalShow] = useState(false);
    const [row, setRow] = useState({
        ImageName: "",
        ImageServerPath: "",
        ImageFullUrl: "",
        ImageUrl: "",
        SiteId: 1,
        CreatedBy: 1,
        CreatedOn: "",
        Id: 0,
        Name: "",
        IsDeleted: 0,
        IsVisible: 1,
        ModifiedBy: 1,
        ModifiedOn: "",
    });
    const [isSubmitClicked, setIsSubmitClicked] = useState(false);
    const [IsDisabled, setIsDisabled] = useState(false);
    const [nameError, setNameError] = useState("");
    const [validated, setValidated] = useState(0);
    const [ImageName, setImageName] = useState("");
    const [base64SelectedImage, setBase64SelectedImage] = useState("");
    const { id } = useParams();
    let content = "";
    const [detail, setDetail] = useState({
        Content: "",
        CreatedBy: 1,
        CreatedOn: "",
        Id: 0,
        IsDeleted: 0,
        IsVisible: 1,
        ModifiedBy: 1,
        ModifiedOn: "",
        Name: "",
        SiteId: 1,
    });

    useEffect(() => {
        let abortController = new AbortController();
        let mounted = true;
        const fetchData = async () => {
            try {
                setLoader(true);
                let apiUrl = process.env.REACT_APP_IMAGEGALLERYAPI + "/getbyId/" + id;
                const response = await fetch(apiUrl, {
                    signal: abortController.signal,
                });
                const json = await response.json();
                const resultPages = json ? json.list : "";
                if (resultPages && resultPages.length > 0) {
                    //debugger;
                    let firstRow = resultPages[0];
                    let isEnabled = false;
                    if (firstRow.IsVisible === 1 || firstRow.IsVisible === true) {
                        isEnabled = true;
                    }

                    let newDetailPage = {
                        Id: firstRow.Id,
                        Name: firstRow.Name,
                        Content: firstRow.Content                                                    
                    };

                    if (mounted) {
                        setDetail(newDetailPage);
                    }

                    let itemRows = [];
                    for (let item of resultPages) {
                        let row = {
                            Id: item.DetailId,
                            ImageSliderId: item.ImageSliderId,
                            ImageName: item.ImageName,                              
                            ImageFullUrl: item.ImageFullUrl,                                                           
                        };
                        if (item.ImageFullUrl) {
                            itemRows.push(row);
                        }
                    }
                    if (itemRows && itemRows.length > 0) {
                        if (mounted) {
                            setList(itemRows);
                        }
                    }
                }
                setLoader(false);
                //abortController = null;
            } catch (err) {
                setLoader(false);
                if (err.name === "AbortError") {
                    // Handling error thrown by aborting request
                }
            }
        };
        fetchData();
        // Side-effect logic...
        return () => {
            // Side-effect cleanup
            mounted = false;
            abortController.abort();
            console.log("unmounting...");
        };
    }, []);

    const [imageCropWidth, setImageCropWidth] = useState(100);
    const [imageCropHeight, setImageCropHeight] = useState(100);

    const [crop, setCrop] = useState({ x: 0, y: 0 });
    const [zoom, setZoom] = useState(1);
    const [aspect, setAspect] = useState(1);
    const [croppedAreaPixels, setCroppedAreaPixels] = useState(null);
    const [croppedImage, setCroppedImage] = useState(null);
    const [cropSize, setCropSize] = useState({ width: 100, height: 100 });
    const [Image, setImage] = useState("");
    const [rotation, setRotation] = useState(0);
    const [cropShape, setCropShape] = useState("rect");

    const onSaveImage = useCallback(
        async (e) => {
            e.preventDefault();
            if (validate() < 0) {
                return -1;
            }
            try {
                let filename = "";
                let base64Image = "";
                let blobUrl = "";
                debugger;               
                const cropImage = await getCroppedImg(Image, croppedAreaPixels, rotation);                
                setCroppedImage(cropImage);
                setImage(cropImage);
                base64Image = cropImage ? cropImage.replace(/^data:image\/(png|jpeg);base64,/, "") : "";
                const contentType = "image/jpeg";
                if (cropImage) {
                    debugger;                
                    setRow((prevState) => {                        
                        return {
                            ...prevState,                            
                            ["ImageFullUrl"]: cropImage,
                            ["ImageName"]: ImageName ? ImageName : "",
                        };
                    });

                    filename = ImageName ? ImageName : "";                    
                    const settings = {
                        method: "POST",
                        headers: {
                            "Content-Type": "application/json",
                        },
                        body: JSON.stringify({
                            filename: filename,
                            image: base64Image,
                        }),
                    };
                    setLoader(true);
                    let submitUrl = process.env.REACT_APP_SERVER_DOMAIN + `/uploaddetail`;
                    const responseMain = await fetch(submitUrl, settings);
                    const jsonRes = await responseMain.json();
                    if (jsonRes) {
                        let convertedJson = jsonRes;
                        if (convertedJson) {
                            setLoader(false);
                            const uploadedImageUrl = convertedJson.fullurl; // get saved image url
                            const uploadedImageName = convertedJson.imagename;
                            const uploadedServerPath = convertedJson.serverpath;
                            const uploadurl = convertedJson.url;
                            setImageName(convertedJson.imagename);                         
                            setRow((prevState) => {                                
                                return {
                                    ...prevState,
                                    ["ImageName"]: uploadedImageName,
                                    ["ImageServerPath"]: uploadedServerPath,
                                    ["ImageFullUrl"]: uploadedImageUrl,
                                    ["ImageUrl"]: uploadurl,
                                };
                            });
                            if (uploadedImageUrl) {
                                setIsDisabled(false);
                            }
                            setUModalShow(false);                                                        
                            setDetail((prevState) => {                                
                                return {
                                    ...prevState,
                                    ["Content"]: content,
                                };
                            });
                        }
                    }
                }
            } catch (err) {               
                console.log(err);
                showToast("Error!", "Image couldn't be saved");
            } finally {
            }
        },
        [croppedAreaPixels, rotation]
    );

    const showImageForCrop = useCallback(
        async (e) => {
            debugger;
            let localSrc = e.ImageFullUrl; //e.target.src;
            setImage(localSrc);
            setUModalShow(true);
            setImageName(e.ImageName);
            setCropSize({ width: imageCropWidth ? parseInt(imageCropWidth) : 0, height: imageCropHeight ? parseInt(imageCropHeight) : 0 });
            if (list && list.length > 0) {
                const selectedIndex = list.findIndex((item) => item.Id === e.Id);
                if (selectedIndex > -1) {
                    setRow(list[selectedIndex]);
                }
            }
        },
        [row]
    );

    const singlefileSelectedHandler = async (e) => {
        //debugger;
        e.preventDefault();
        setIsDisabled(true);
        content = "";

        if (!e.target.files || e.target.files.length <= 0) {
            return -1;
        }

        if (detail && detail.Content) {
            content = detail.Content;
        }
        //let imageList = "";
        const selectedImage = e.target.files[0];
        let imageSizeInMBs = selectedImage.size ? selectedImage.size / 1024 / 1024 : 0;
        if (selectedImage && imageSizeInMBs > 8) {
            setIsDisabled(false);            
            setRow((prevState) => {                
                return {
                    ...prevState,
                    ["ImageName"]: "",
                    ["ImageServerPath"]: "",
                    ["ImageFullUrl"]: "",
                    ["ImageUrl"]: "",
                };
            });
            showToast("Information!", "Image size can't be greater than 8MB.");
            return -1;
        }
        
        const filename =
            selectedImage && selectedImage.name
                ? new Date().valueOf() +
                  "_" +
                  selectedImage.name.replace(/\\/g, "").replace(/ /g, "").replace(/'/g, "").replace(/"/g, "").replace(/`/g, "")
                : "";        
        setUModalShow(false);
        setCropSize({ width: imageCropWidth ? parseInt(imageCropWidth) : 0, height: imageCropHeight ? parseInt(imageCropHeight) : 0 });
        setImageName(filename);
        setUModalShow(true);
        let convertedImageFile = await convertImage(selectedImage);
        setBase64SelectedImage(convertedImageFile);       
    };

    async function convertImage(file) {
        return new Promise((resolve, reject) => {           
            var reader = new FileReader();
            reader.readAsDataURL(file);
            reader.onload = function (e) {
                e.preventDefault();
                let base64 = e.target.result;
                base64 = base64.replace(/^data:image\/(png|jpeg);base64,/, "");
                setImage(reader.result);

                resolve(base64);
                //resolve(reader.result);
            };
            reader.onerror = function (error) {
                console.log("Error: ", error);
                reject(error);
            };
        });
    }
    const onAddSide = (e) => {
        //debugger;
        let newImageList = [...list];
        if (row.Id && row.Id > 0) {
            if (newImageList && newImageList.length > 0) {
                const selectedIndex = newImageList.findIndex((item) => item.Id === row.Id);
                if (selectedIndex > -1) {
                    newImageList[selectedIndex] = row;
                }
            }
        } else {
            row.Id = Math.max.apply(
                Math,
                newImageList.map(function (o) {
                    return o.Id + 1;
                })
            );
            if (!row.Id || (row.Id && row.Id === 0) || row.Id === -Infinity) {
                row.Id = 1;
            }
            newImageList.push(row);
        }
        setList(newImageList);
        
    };

    const onCropComplete = useCallback((croppedArea, croppedAreaPixels) => {
        //debugger;
        setCroppedAreaPixels(croppedAreaPixels);
    }, []);

    const onClose = useCallback(() => {
        setCroppedImage(null);
    }, []);

    const onCropperZoomChange = (e) => {
        if (e && e.currentTarget && e.currentTarget.value) {
            let lZoomValue = e.currentTarget.value;
            if (lZoomValue && lZoomValue < 0.4) {
                //setZoom(0.28);
                setZoom(0.4);
            } else if (lZoomValue && lZoomValue > 1) {
                setZoom(1);
            } else {
                setZoom(lZoomValue);
            }
        }
    };

    return (
        <Page breadcrumb={breadcrumb} pageName={pageName} fluid>
            <form noValidate validated={validated} onSubmit={HandleSaveMenu} className="user-form">
                <Card>
                    <Card.Header>
                        <TitleBar title="Edit Gallery" />
                    </Card.Header>
                    <Card.Body>
                        <div className="form-row">                                
                            <div className="form-group col-md-2">
                                <label className="form-label" htmlFor="ImageCropWidth">
                                    Width
                                </label>
                                <input
                                    name="ImageCropWidth"
                                    id="ImageCropWidth"
                                    className={`form-control`}
                                    value={imageCropWidth}
                                    onChange={(e) => setImageCropWidth(e.target.value)}
                                />
                            </div>
                            <div className="form-group col-md-2">
                                <label className="form-label" htmlFor="ImageCropWidth">
                                    Height
                                </label>
                                <input
                                    name="ImageCropWidth"
                                    id="ImageCropWidth"
                                    className={`form-control`}
                                    value={imageCropHeight}
                                    onChange={(e) => setImageCropHeight(e.target.value)}
                                />
                            </div>                                
                        </div>
                        <SingleGalleryRow
                            data={row}
                            setRow={setRow}
                            onUpload={singlefileSelectedHandler}
                            onAddSide={onAddSide}
                            IsDisabled={IsDisabled}
                        />

                        <ul className="slide-list">
                            {list &&
                                list.map(function (item, i) {
                                    //debugger;
                                    return (
                                        <li key={i}>
                                            <div className="slide-row">
                                                <div className="img-holder">
                                                    <img
                                                        className="thumbnail"
                                                        src={item.ImageFullUrl}
                                                        alt={item.ImageName}
                                                        onClick={() => showImageForCrop(item)}
                                                    />
                                                </div>
                                            </div>
                                        </li>
                                    );
                                })}
                        </ul>
                    </Card.Body>
                    <Card.Footer>
                        <div className="btn-holder text-right">
                            <Button type="submit" variant="primary" disabled={isSubmitClicked}>
                                Save
                            </Button>
                        </div>
                    </Card.Footer>
                </Card>
            </form>
            <CenteredPopup
                show={umodalShow}
                onHide={() => setUModalShow(false)}
                title="Crop Image"
                content=""
                closetext="Close"
                savetext="Apply"
                onSaveChanges={onSaveImage}
            >
                <div className="cropimage-container">
                    <div className="cropimage-tools">
                        <span className="cropimage-icons" onClick={(e) => setCropShape("rect")}>
                            <MdOutlineCrop />
                            <span className="cropimage-text">Crop</span>
                        </span>
                        <span className="cropimage-icons" onClick={(e) => setCropShape("round")}>
                            <MdOutlineCircle />
                            <span className="cropimage-text">Circle</span>
                        </span>
                    </div>
                    <div className="crop-container">
                        <Cropper
                            image={Image}
                            crop={crop}                              
                            cropSize={cropSize}
                            cropShape={cropShape}
                            zoom={zoom || 1}
                            showGrid={true}
                            zoomWithScroll={false}
                            objectFit="horizontal-cover"
                            onCropChange={setCrop}
                            onCropComplete={onCropComplete}
                            onZoomChange={onCropperZoomChange}
                        />
                    </div>
                </div>
                <div className="form-row ic_rangeslider">
                    <div className="form-group col-md-12">
                        <label className="form-label" htmlFor="ZoomBtn">
                            {zoom || 1}
                        </label>
                        <span className="range-slider__wrap">
                            <input
                                id="zoomrangeid"
                                type="range"
                                className="slider range-slider range-slider--light"
                                value={zoom || 1}
                                min={0.4}
                                max={1}
                                step={0.1}
                                aria-labelledby="Zoom"
                                onChange={onCropperZoomChange}
                            />
                        </span>
                    </div>
                </div>
            </CenteredPopup>
        </Page>
    );
}    
export default withRouter(EditImage);
0 Answers
Related