I want to get image from backend to frontend in MERN Stack - node.js

I want to get image from backend to frontend in MERN Stack. all data gets about product also gets image title but images cannot render.
I want to get image from backend to frontend in MERN Stack. all data gets about product also gets image title but images cannot render
I want to get image from backend to frontend in MERN Stack. all data gets about product also gets image title but images cannot render
I want to get image from backend to frontend in MERN Stack. all data gets about product also gets image title but images cannot render
This is my frontend code
import "./Related.css";
import { NavLink } from "react-router-dom";
import { useSelector, useDispatch } from "react-redux";
import { getMovies } from "../../../Redux/Actions/MoviesAction";
function Related() {
const dispatch = useDispatch();
const moviesList = useSelector((state) => state.MoviesReducer.list);
useEffect(() => {
withoutReload();
});
function withoutReload() {
dispatch(getMovies());
}
const [relatedProducts, setRelatedProducts] = useState(10);
const allProducts = moviesList.slice(0, relatedProducts);
const loadMoreProducts = () => {
setRelatedProducts(relatedProducts + relatedProducts);
};
return (
<>
<div id="related">
<div className="moviesContainer">
{allProducts.map((data, index) => {
return (
<div className="movies" key={index}>
<img src={data.picture} alt={data.picture} />
<div>
<h5 className="mb-0">{data.title}</h5>
<div className="cat">{data.category}</div>
<NavLink to={`/download-movie/${data._id}`}>View</NavLink>
</div>
</div>
);
})}
</div>
<div className="cancelBtn">
<button onClick={() => loadMoreProducts()}>Load More</button>
</div>
</div>
</>
);
}
export default Related;
This is my Backend code
const express = require("express");
const router = express.Router();
const addNewMoviesData = require("../Models/AddNewMovie");
const multer = require("multer");
const storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, "images/");
},
filename: function (req, file, cb) {
cb(null, file.originalname);
},
});
const upload = multer({ storage: storage });
router.post("/addNewMovie", upload.single("picture"), (req, res) => {
const addNewMoviesform = new addNewMoviesData({
picture: req.file.originalname,
title: req.body.title,
genre: req.body.genre,
duration: req.body.duration,
releaseDate: req.body.releaseDate,
size: req.body.size,
language: req.body.language,
description: req.body.description,
link: req.body.link,
category: req.body.category,
subCategory: req.body.subCategory,
});
addNewMoviesform
.save()
.then((data) => {
res.json(data);
})
.catch((error) => {
console.log(error);
});
});

Related

Not getting image file in nodejs after posting from react

I'm sending the image file from react to nodejs. I used the SetImage function where the image file selected by the user is set to the 'myimage' state variable and from handleSubmit I'm posting the images to the '/blog/posts' endpoint using Axios. the image file is getting loaded on the 'myimage' state variable but as I posted using the Axios, I can't see all the data of the image file and giving me the empty object.
This is my React code:-
import React, { useState, useRef } from "react";
import './postblog.css';
import axios from '../axios';
const PostBlog = () => {
const [myimage,setImage] = useState("");
const handleSubmit = (event) => {
event.preventDefault();
axios.post('/blog/posts', {
image:myimage
}).then((res) => {
console.log(res.body);
console.log('successfully posted');
});
}
const SetImage = (e)=>{
console.log(e.target.files[0]);
setImage(e.target.files[0]);
console.log(myimage);
}
return (
<div className="postblog">
<form onSubmit={handleSubmit} enctype="multipart/form-data">
<input type="file" placeholder="Choose your file" onChange={(e)=>{SetImage(e)}} name="myImage"/>
</div>
<button type="submit">Post</button>
</form>
</div>
);
}
export default PostBlog;
This is my Nodejs code:-
var storage = multer.diskStorage({
destination: function(req, res, cb) {
cb(null, './Routers/blog/uploads');
},
filename: function(req, file, cb) {
cb(null, Date.now() + file.originalname);
}
});
var upload = multer({
storage: storage,
limits: {
fieldsize: 1024 * 1024 * 3
}
});
blog.post('/posts', upload.single('myimage'), (req, res, next) => {
console.log(req.body);
console.log(details);
})
The output in the console I'm getting is an empty object
You should send file with content type as multipart/form-data but in your code you are sending file as application/json content type.
...
const handleSubmit = (event) => {
event.preventDefault();
const formData = new FormData();
formData.append('file', myimage);
const config = {
headers: {
'content-type': 'multipart/form-data'
}
};
axios.post('/blog/posts', formData, config).then((res) => {
console.log(res.body);
console.log('successfully posted');
});
}
...

React Hooks and Axios Image Upload with Multer

I am trying to add the ability to upload an image and then update a user object with that image path. When I upload the image using Insomnia client and send the request, I am able to successfully add the image and path to MongoDB. NodeJS user route below:
const express = require ("express");
const router = express.Router();
const bcrypt = require("bcryptjs");
const jwt = require("jsonwebtoken");
const Users = require("../models/users");
const auth = require("../middleware/auth");
const multer = require('multer');
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' || file.mimetype == "image/jpg") {
cb(null, true);
} else {
cb(null, false);
return cb(new Error('Only .png, .jpg and .jpeg format allowed!'));
}
};
const upload = multer({storage: storage, limits: {
fileSize: 1024 * 1024 * 5
},
fileFilter: fileFilter
});
// REQUEST TO FIND USER BY ID AND ADD A PROFILE PICTURE
router.put('/update/:id', upload.single('userImage'), (req, res) => {
Users.findById(req.params.id)
.then(user => {
user.userImage = req.file.path || user.userImage,
user
.save()
.then(() => res.json("The User is UPDATED succesfully!"))
.catch(err => res.status(400).json(`Error: ${err}`));
})
.catch(err => res.status(500).json(`Error: ${err}`));
console.log(req.body);
console.log(req.file);
});
However, when I test the code on the client I receive the following 500 error: ""Error: TypeError: Cannot read property 'path' of undefined." I am using React Hooks and Axios, code below:
import React, { useState, useContext } from 'react';
import Exit from '../cancel.svg';
import Modal from 'react-modal';
import { useForm } from "react-hook-form";
import axios from 'axios';
import UserContext from "../context/UserContext";
import { useHistory } from "react-router-dom";
Modal.setAppElement('#root');
const ProfilePicture = () => {
const [modalIsOpen, setModalIsOpen]= useState (true);
const { register, handleSubmit } = useForm ();
const [userImage, setUserImage] = useState();
const onSubmit = (data) => console.log(data);
const { userData } = useContext(UserContext);
const history = useHistory();
const changeOnClick = e => {
const users = {
userImage
};
console.log(users);
axios
.put(`http://localhost:5000/users/update/${userData.user.id}`, users)
.then(res => console.log(res.body))
.catch(err => {
console.log(err);
});
history.push("/Landing")
}
return(
<Modal isOpen={modalIsOpen} onRequestClose={() => setModalIsOpen(false)} className='finishBorder'>
<div className='border-bottom-two'>
<img onClick= {() => setModalIsOpen(false)} className='newexitButton'src={Exit} alt='X' />
<span className='lastThing'>One last thing! Add a profile picture</span>
</div>
<form onSubmit={handleSubmit(changeOnClick)} encType="multipart/form-data" >
<div>
<span className="dot"></span>
<input onChange={e => setUserImage(e.target.value)} ref = {register} type='file' name='userImage' className='picUploader'/>
{/* <button>submit</button> */}
</div>
<div>
<button type='submit' className='doneButton'>Done</button>
<div>
<span className='laterTwo'>I'll do this later</span>
</div>
</div>
</form>
</Modal>
)
}
export default ProfilePicture;
Appreciate the help!
What you are sending from the client is a "fakepath", not a file. To access the file from the input use:
setUserImage(e.target.files[0])
Also, I think multer only works with multipart/form-data, so you should check that, but is as easy as:
const formData = new FormData();
formData.append([image name], [image file]);
axios.post(`http://localhost:5000/users/update/${userData.user.id}`, formData, {
headers: { "Content-Type": "multipart/form-data" }})

Why does my DataForm not return as an object that my URL.createObjectURL is supposed to read?

All I am trying to accomplish is to give my users the option to upload images. I decided to use mongoDB as my database which means I must store photos locally and then send them to the DB. As far as I know, I am new. The object created by ImageName and ImageData isn't being passed properly to my axios post request
.post(`http://localhost:5000/api/image/uploadmulter/`, imageFormObj)
.then((data) => {
if (data.data.success) {
alert("Image has been successfully uploaded using multer");
this.setDefaultImage("multerImage");
}
})
Here is my route
const Image = require('../models/imageModel');
const ImageRouter = express.Router();
const multer = require('multer');
const storage = multer.diskStorage({
destination: function (req, file, cb){
cb(null, './uploads/')
},
filename: function(req,file,cb){
cb(null, Date.now() + file.originalname);
}
});
const fileFilter = (req, file, cb) =>{
if(file.mimetype === 'image/jpeg' || file.mimetype ==='image/png'){
cb(null, true);
} else{
//rejects storing file
cb(null, false);
}
};
const upload = multer({
storage: storage,
limits:{
fileSize:1024 *1024 * 5
},
fileFilter: fileFilter
});
// stores image in uploads folder using multers and creates a reference to the file
ImageRouter.route("/upload")
.post(upload.single('imageData'), (req, res, next) => {
console.log(req.body);
const newImage = new Image({
imageName: req.body.imageName,
imageData: req.file.path
});
newImage.save()
.then((result)=>{
console.log(result)
res.status(200).json({
success: true,
document: result
});
})
.catch((err)=> next(err))
});
module.exports = ImageRouter;
here is my model
const Schema = mongoose.Schema;
const ImageSchema = new Schema({
imageName:{
type: String,
default: "none",
required: true
},
imageData: {
type :String,
required: false
}
});
const Image = mongoose.model('Image' , ImageSchema)
module.exports = Image;
Here is my ImageUploader page that calls the function
import axios from 'axios';
import DefaultImg from '../assets/default-img.jpg';
import 'bootstrap/dist/css/bootstrap.min.css';
export default class ImageUploader extends Component {
constructor(props) {
super(props)
this.state = {
multerImage: DefaultImg
}
};
setDefaultImage = (uploadType) => {
if (uploadType === "multer") {
this.setState({multerImage: DefaultImg});
};
};
// function to upload image once it has been captured include multer and
// firebase methods
uploadImage(e, method) {
let imageObj = {};
if (method === "multer") {
let imageFormObj = new FormData();
imageFormObj.append("imageName", "multer-image-" + Date.now());
imageFormObj.append("imageData", e.target.files[0]);
console.log(imageFormObj)
// stores a readable instance of the image being uploaded using multer
this.setState({
multerImage: URL.createObjectURL(e.target.files[0])
});
axios
.post(`http://localhost:5000/api/image/uploadmulter/`, imageFormObj)
.then((data) => {
if (data.data.success) {
alert("Image has been successfully uploaded using multer");
this.setDefaultImage("multerImage");
}
})
.catch((err) => {
alert("Error while uploading image using multer");
this.setDefaultImage("multer");
});
}
};
render() {
return (
<div className="main-container">
<h3 className="main-heading">Image Upload App</h3>
<div className="image-container">
<div className="process">
<h4 className="process__heading">Process: Using Multer</h4>
<p className="process__details">Upload image to a node server, connected to a
MongoDB database, with the help of multer</p>
<input
type="file"
display="block"
className="process__upload-btn"
placeholder="Username"
onChange={(e) => this.uploadImage(e, "multer")
}/>
<img
src={this.state.multerImage}
alt="upload-image"
className="process__image"/>
</div>
</div>
</div>
);
};
};
and finally this is where it's being rendered
// import {EditProfile} from './EditProfile'
import DisplayCats from '../cats/DisplayCats'
// import Button from '#material-ui/core/Button';
import Axios from 'axios';
import ImageUploader from '../ImageUploader';
function ProfilePage(props) {
console.log(props.userInfo)
const user = props.userInfo
console.log(user)
console.log(user._id)
console.log(props.userInfo._id)
let [responseData,
setResponseData] = useState('');
// getLocation = () => {
// navigator
// .geolocation
// .getCurrentPosition(function (position) {
// console.log(position)
// });
// }
const clickHandler = (e) => {
this
.props
.history
.push('/DisplayCats')
}
// const setProfileImage = (event) => {
// Axios
// .post('http://localhost:5000/api/users/updateImage/' + user._id, {
// "_id": user._id,
// "profileImage": event.target.value
// })
// .then(res => {
// setResponseData(res.data)
// console.log(responseData)
// }, function (err) {
// console.log(err)
// })
// }
return (
<div style={{
color: "black"
}}>
<h5>This is {props.userInfo.firstName}'s Profile Page</h5>
<h5>Last name: {props.userInfo.lastName}</h5>
<h5>Age: {props.userInfo.age}</h5>
<h5>Location:{props.userInfo.location}</h5>
<h5>Image:{props.userInfo.profileImage}</h5>
<h5>Biography:{props.userInfo.biography}</h5>
<ImageUploader user={user}/>
{/* <div className="col-md-6 img">
<img
src={responseData.profileImage}
alt="profile image"
className="img-rounded"/>
</div> */}
<div className="row">
<DisplayCats user={user}/>
</div>
{/*
<Button
variant="outlined"
color="primary"
onClick={this.clickHandler}
component={this.EditProfile}
user={this.props.user}>
Edit Info
</Button> */}
</div>
)
}
export default ProfilePage;
I want my image data and and image name to be created into a URL for my other functions to read it. My error comes back as POST /api/image/uploadmulter/ 404 97.290 ms - 163
Perhaps im missing something but from the code you shared, you set your route as:
ImageRouter.route("/upload")
so, your client side code should be posting to: http://localhost:5000/upload
yet, your code does this:
.post(`http://localhost:5000/api/image/uploadmulter/`
You're getting a 404 error, which makes sense since this route hasn't been defined.
On a related note, I'd recommend using something like react-uploady, to manage the uploads on your client-side. It will save you a lot of code and bugs. Especially if you want to show preview or other related functionality (like: progress, cancel, retry, etc.).

Uploading CSV file from react front end to node.js backend and storing it in the folder

I'm trying to upload a file to the backend folder using react's front end form input but I'm unable to do so.
I've added the form, I tried capturing data in the state but for some reason I can't store csv file in a state, is it because of file complexity?
Since I couldn't get the state to store my csv, I used axios to push data straight to the backend which seemed to work but the file was not saved in the backend.
I have 3 files, react App and node Upload
import React, {Component} from 'react';
import logo from './logo.svg';
import './App.css';
import CSVReader from 'react-csv-reader';
import axios from 'axios';
class App extends Component {
constructor(props) {
super(props);
this.state = {
apiResponse: '',
file: null,
};
this.handleImport = this.handleImport.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
callAPI() {
fetch("http://localhost:9000/testAPI")
.then(res => res.text())
.then(res => this.setState({ apiResponse: res }));
console.log(this.state.apiResponse)
}
componentDidMount() {
this.callAPI();
}
handleImport(data){
this.setState({file:data.target.files[0]})
//because I couldn't get state to work I used axios imediately with the data
axios.post("http://localhost:9000/upload", data, { // receive two parameter endpoint url ,form data
}).then(res => { // then print response status
console.log(res.statusText)
})
}
//I'm not using handlesubmit here as it involves a button press
handleSubmit(e){
e.preventDefault();
const data = new FormData();
data.append('file', this.state.file);
console.log(data);
axios.post("http://localhost:9000/upload", data, { // receive two parameter endpoint url ,form data
}).then(res => { // then print response status
console.log(res.statusText)
})
}
render() {
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p className='App-intro'> {this.state.apiResponse}</p>
</header>
<content className='body_cont'>
{/* My Form */}
<form action="POST">
<input type="file" name='file' onChange={this.handleImport} />
<button type='submit' onClick={this.handleSubmit}>Upload File</button>
</form>
</content>
</div>
);
}
}
export default App;
Next file is my upload file for which the routes have been set in app.js
var express = require('express');
var multer = require('multer');
var router = express.Router();
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, '../folder1/folder2/dm-portal/in')
},
filename: function (req, file, cb) {
cb(null, Date.now() + '-' +file.originalname )
}
});
var upload = multer({ storage: storage }).single('file')
router.post('/',function(req, res) {
console.log(req)
upload(req, res, function (err) {
if (err instanceof multer.MulterError) {
return res.status(500).json(err)
} else if (err) {
return res.status(500).json(err)
}
return res.status(200).send(req.file)
})
});
module.exports = router;
End results is I get a whole bunch of warning but the axios seemed to be working, however, the files is not being saved.
Any help appreciated.
P.S. I'm beginner.

File upload using multer

I am trying to make a web app that you can upload files to using express and multer, and I am having a problem that no files are being uploaded and req.file is always undefined.I have checked multiple solutions but none of them is working.
My reactjs component is as follows:
onSubmit(e) {
e.preventDefault();
const productData = {
name: this.state.name,
image: this.state.image,
description: this.state.description,
category: this.state.category,
quantity: this.state.quantity,
price: this.state.price
};
console.log(productData.image);
this.props.createProduct(productData, this.props.history);
}
onChange(e) {
this.setState({ [e.target.name]: e.target.value });
}
<form onSubmit={this.onSubmit} encType="multipart/form-data">
<UploadImage
name="image"
value={this.state.image}
onChange={this.onChange}
error={errors.image}
type="file"
info="Upload image of the product"
/>
<input
type="submit"
value="Submit"
className="btn btn-info btn-block mt-4"
/>
</form>
My router file is as follows:
const express = require("express");
const router = express.Router();
const multer = require("multer");
const path = require("path");
//Loading validation function
const validateProductInput = require("../../validation/product.js");
//Load product model
const Product = require("../../models/Product");
//#route GET api/products/test
//#desc Test product route
//#access public
router.get("/test", (req, res) => res.json({ msg: "Profile Works" }));
//Creating a multer API to upload images
const storage = multer.diskStorage({
destination: "../../uploads",
filename: function(req, file, cb) {
cb(
null,
file.fieldname + "." + Date.now() + path.extname(file.originalname)
);
}
});
//Init Upload
const upload = multer({
storage: storage
});
//#route Post api/products/add
//#desc Add product
//#access Private
router.post("/add", upload.single("image"), (req, res) => {
const { errors, isValid } = validateProductInput(req.body);
if (!isValid) {
//Return any erros with 400 status
return res.status(400).json(errors);
}
console.log("File: ", req.file);
Product.findOne({
name: req.body.name
}).then(product => {
if (product) {
errors.exist = "Item Already Exists";
return res.status(400).json(errors);
} else {
// let image_path = req.body.image;
// image_path = image_path.replace(
// /fakepath/g,
// "projects\\e-commerce\\MERN-eCommerce\\client\\src\\components\\dashboard\\images"
// );
const newProduct = new Product({
name: req.body.name,
image: req.body.image,
description: req.body.description,
category: req.body.category,
quantity: req.body.quantity,
price: req.body.price
});
newProduct
.save()
.then(product => res.json(product))
.catch(err => res.status(404).json());
}
});
});
//Upload image component
const UploadImage = ({ name, value, type, error, info, onChange }) => {
// Add the following code if you want the name of the file appear on select
$(".custom-file-input").on("change", function() {
var fileName = $(this)
.val()
.split("\\")
.pop();
$(this)
.siblings(".custom-file-label")
.addClass("selected")
.html(fileName);
});
return (
<div className="custom-file">
<input
className={classnames(
"custom-file-input form-control form-control-lg",
{
"is-invalid": error
}
)}
name={name}
type={type}
value={value}
onChange={onChange}
/>
<label className="custom-file-label">Choose file</label>
{info && <small className="form-text text-muted">{info}</small>}
{error && <div className="invalid-feedback">{error}</div>}
</div>
);
};
UploadImage.propTypes = {
name: PropTypes.string.isRequired,
placeholder: PropTypes.string,
value: PropTypes.string.isRequired,
info: PropTypes.string,
error: PropTypes.string,
onChange: PropTypes.func.isRequired
};
export default UploadImage;
console.log("File: ", req.file); is always giving undefined and no file is uploaded to the uploads directory

Resources