Not able to view the Uploaded image (on the backend server) using Webpack with url-loader/file-loader in React

182 views Asked by At

I am working on a FileUploader ( Images for now) which will enable the user to upload multiple files to the backend server in one go.

I have the following setup

  1. Webpack configured with url-loader supporting all kinds of images.
  2. I have a React client running on port 9002 inside separate directory called client. This has a component called "UploadDocumentsContainer". This component will let user select multiple input files to upload. The component makes axios call to backend server at end-point "/uploads".
  3. A Backend node server is running one directory up then client directory running on port 9001. It has a uploads endpoint configured to cater to the uploaded images. The server moves the images to /client/public/uploads and send the response back to client with fileName and filePath of the image.
  4. The React client also has a Separate component called ProgressFileUpload which gets fired up once upload starts from 0 to 100% depending on the upload status.

The Problem So far is as follows.

  1. The image gets successfully uploaded to server and we get the 200 response back from server with the fileName and filePath of the image.
  2. But during rendering the same uploaded images using DisplayFile component the app crashes with following error.

I have been trying to get this working since last 3 days . I have gone through lots of github and stackoverflow post but didnt find the solution for the same. I will really appreciate if i can get some input/feedback/solution on the same.

My Guess is that there is something wrong with my Webpack.configs (publicPath or url-loader) or the filePath of the images is not pointing in the right direction after bundle is made.

The above error occurred in the component: in DisplayFile (created by UploadDocumentsContainer) in form (created by UploadDocumentsContainer) in div (created by UploadDocumentsContainer) in div (created by UploadDocumentsContainer) in div (created by UploadDocumentsContainer) in UploadDocumentsContainer

Error: Cannot find module './wallpaper-1680x1050.jpg' bundle.js line 96 > eval:14:11
TypeError: _context.t0.response is undefined

Sandbox link is throwing error "Request failed with status code 422"

GITHUB LINK:- https://github.com/aryan21710/FileUploader.git

Webpack.config.js:-

const path = require("path");
const webpack = require("webpack");
const dotenv=require("dotenv");


module.exports = () => {
     // call dotenv and it will return an Object with a parsed key 


  return {
    mode: "development",
    // babel-polyfill allows us to use all the latest es7 javascript features like Array.includes , Array.from and so on
    // 
    entry: ["babel-polyfill", path.join(__dirname, "client/src/app.js")],
    devServer: {
      proxy: {
        "/client/public/uploads/": "http://localhost:9001"
      },
      // index.html will be inside build and not dist after installing htmlWebpackPlugin.
      contentBase: path.join(__dirname, "client", "public", "build"),
      hot: false,
      inline: true,
      historyApiFallback: true,
      watchContentBase: true,
      port: 9002,
      watchOptions: {
        ignored: [
          path.resolve(__dirname, "fileUploadServer/server.js"),
          path.resolve(__dirname, "node_modules/")
        ]
      }
    },
    output: {
      path: path.join(__dirname, "client", "public", "build"),
      // Will generate a new bundle.js with name "main.somerandomhash.bundle.js" every time when app changes.
      filename: "bundle.js",
    },
    module: {
      rules: [
        {
          loader: "babel-loader",
          test: /\.js$/,
          exclude: /node_modules/
        },
        {
          test: /\.s?css$/,
          use: ["style-loader", "css-loader", "sass-loader"]
        },
        {
          test: /\.(jpe?g|png|gif|woff|woff2|eot|ttf|svg|jpg)$/,
          loader: "url-loader",

        }
      ]
    },
    devtool: "cheap-module-eval-source-map"
  };
};

UploadDocumentsContainer.js:-

import React, { useState } from "react";
import { useHistory } from "react-router-dom";
import axios from "axios";
import ProgressFileUpload from "./ProgressFileUpload";

const UploadDocumentsContainer = () => {
  const [selectedFile, setSelectedFile] = useState("Choose File");
  const [displayFile, setDisplayFile] = useState([]);
  const [file, setFile] = useState([]);
  const [uploadPercentage, setUploadPercentage] = useState(0);





  const onChangeFile = event => {
    console.log("event.target.files", event.target.files[0]);

    for (let i = 0; i < event.target.files.length; i++) {
      let _ = event.target.files[i];
      setFile(file => [...file, _]);
    }
    event.target.files.length > 1
      ? setSelectedFile(`${event.target.files.length} Files`)
      : setSelectedFile(event.target.files[0].name);
  };

  const onUpload = async e => {
    e.preventDefault();
    console.log("file", file);
    console.log("selectedFile", selectedFile);
    const formData = new FormData();
    file.forEach(_ => {
      console.log("_", _);
      formData.append("file", _);
    });
    console.log("FORMDATA INSIDE UploadDocumentsContainer", formData);

    try {
      const response = await axios.post(
        "http://localhost:9001/client/public/uploads",
        formData,
        {
          headers: {
            "Access-Control-Allow-Origin": "*",
            "Content-type": "multipart/form-data"
          },
          onUploadProgress: progressEvent => {
            setUploadPercentage(
              parseInt(
                Math.round((progressEvent.loaded * 100) / progressEvent.total)
              )
            );

            // Clear percentage
            setTimeout(() => setUploadPercentage(0), 10000);
          }
        }
      );

      let { fileName, filePath } = response.data;
      console.log("response.data", response.data);
      fileName = fileName.split(",");
      filePath = filePath.split(",");
      console.log("fileName", fileName);
      console.log("filePath", filePath);

      setDisplayFile(displayFile => [...displayFile, ...fileName]);
      console.log(
        "displayFile from the server",
        displayFile,
        ":",
        displayFile.length
      );
      console.log("response back from server:-", fileName, " AND ", filePath);

      // const importAll = r => {
      //   return r.keys().map(r);
      // };

      // setImages(
      //   importAll(
      //     require.context(
      //       "./../../../../../../../public/uploads/",
      //       false,
      //       /\.(png|jpeg|svg|jpg)$/
      //     )
      //   )
      // );
    } catch (error) {
      if (error.response.status == 500) {
        console.log("There was a problem with the server");
      } else {
        console.log(error.response.data.msg);
      }
    }
  };

  const DisplayFile = () => {
    console.log("displayFile", displayFile);
    console.log("uploadPercentage", uploadPercentage);
    return (
      <div className="displayFileContainer">
        {displayFile.length > 0
          ? displayFile.map((_, idx) => {
              const myimg = require(`./../../../../../../../public/uploads/${_}`)
                .default;
              console.log("myimg", myimg);
              return (
                <div className="fileDimension" key={idx}>
                  <img src={myimg} />
                </div>
              );
            })
          : null}
      </div>
    );
  };

  return (
    <div className="formOuterWrapper">
      <div className="formInnerWrapper">
        <div className="fileUploadContainer">
          <form className="fileUploadForm " name="myForm" onSubmit={onUpload}>
            <div className="custom-file mb-5">
              <input
                type="file"
                multiple
                className="custom-file-input"
                id="customFile"
                onChange={onChangeFile}
              />
              <label className="custom-file-label" htmlFor="customFile">
                {selectedFile}
              </label>
            </div>

            <div className="progressbar">
              <ProgressFileUpload percentage={uploadPercentage} />
            </div>

            <input
              type="submit"
              value="Upload"
              className="btn btn-primary btn-block mt-5"
            />
            <DisplayFile />
          </form>
        </div>
      </div>

    </div>
  );
};

export default UploadDocumentsContainer;

Backend FILE Server(fileUploadServer):-

const express = require("express");
const fileUpload = require("express-fileupload");
const morgan = require("morgan");

const app = express();
const path = require("path");
const cors = require("cors");
const port = 9001;
const publicPath = path.join(__dirname, "..", "client", "public");
// eslint-disable-next-line no-console
console.log("publicpath", publicPath);
app.use(express.static(publicPath));
app.use(cors());
app.use(fileUpload());
app.use(morgan("dev"));

app.post("/client/public/uploads", (req, res) => {
  if (req.files === null) {
    return res.status(400).json({ msg: "NO FILE UPLOADED" });
  }



  const filename = [],
    filepath = [];
  if (Object.keys(req.files.file).includes("name")) {
    const file = req.files.file;
    filename.push(file.name);
    filepath.push(`${publicPath}/uploads/${file.name}`);
    file.mv(`${publicPath}/uploads/${file.name}`, err => {
      if (err) {
        console.log("err while moving the file to different directory", err);
        return res.status(500).send(err);
      }
    });
  } else {
    for (let i in req.files.file) {
      const file = req.files.file[i];
      filename.push(file.name);
      filepath.push(`${publicPath}/uploads/${file.name}`);
      console.log("INSIDE UPLOADS", file.name);
      file.mv(`${publicPath}/uploads/${file.name}`, err => {
        if (err) {
          console.log("err while moving the file to different directory", err);
          return res.status(500).send(err);
        }
      });
    }
  }

  console.log(filename, "::::", filepath);

  res.json({ fileName: `${[filename]}`, filePath: `${filepath}` });
});
app.listen(port, () => {
  // eslint-disable-next-line no-console
  console.log(`SERVER IS LISTENING ON PORT ${port}`);
});

Directory Structure:-

enter image description here

0

There are 0 answers