'How to Use Multer and Fileupload Both in Node js For uploading Images Using Cloudinary
I want a solution about how can I use both packages express-fileupload and multer for uploading images I am trying to use both simultaneously but when I post a post on my website then it caught me error but when I comment out below line then it works
const express = require("express");
const fileUpload = require('express-fileupload');
const app = express();
app.use(fileUpload({
useTempFiles: true
}));
But for users, it does not change the user avatar on my website how can I solve this problem by using only multer?
Server.js (Backend)
const dotenv = require('dotenv');
const express = require("express");
const bodyparser = require('body-parser');
const connectDB = require('./config/db');
const cors = require('cors');
const errorHandler = require("./middleware/error");
const fileUpload = require('express-fileupload');
const cookieParser = require('cookie-parser');
const app = express();
app.use(bodyparser.json());
app.use(cors());
app.use(cookieParser());
app.use(fileUpload({
useTempFiles: true
}));
app.use('/', express.static('uploads'));
app.use(bodyparser.urlencoded({ extended: false }));
app.get("/", (req, res, next) => {
res.send("Api running");
});
// Connecting Routes
app.use('/', require('./routes/indexpost'));
app.use('/user', require('./routes/userRouter'));
app.use('/api', require('./routes/upload'));
app.use("/comments", require("./controllers/Comments"));
// app.use('/comments', require('./routes/Comments'));
// Error Handler Middleware
app.use(errorHandler);
// load config
dotenv.config();
connectDB();
const PORT = process.env.PORT || 5000;
app.listen(PORT, () =>
console.log(`Sever running on port ${PORT}`)
);
Upload.js (Backend)
const router = require('express').Router()
const uploadImage = require('../middleware/uploadImage')
const uploadCtrl = require('../controllers/uploadCtrl')
const auth = require('../middleware/auth')
router.post('/upload_avatar', uploadImage, auth, uploadCtrl.uploadAvatar)
module.exports = router
uploadimage.js
const fs = require('fs');
module.exports = async function(req, res, next) {
try {
if(!req.files || Object.keys(req.files).length === 0)
return res.status(400).json({msg: "No files were uploaded."})
const file = req.files.file;
if(file.size > 1024 * 1024){
removeTmp(file.tempFilePath)
return res.status(400).json({msg: "Size too large."})
} // 1mb
if(file.mimetype !== 'image/jpeg' && file.mimetype !== 'image/png'){
removeTmp(file.tempFilePath)
return res.status(400).json({msg: "File format is incorrect."})
}
next()
} catch (err) {
return res.status(500).json({msg: err.message})
}
}
const removeTmp = (path) => {
fs.unlink(path, err => {
if(err) throw err
})
}
uploadCtrl.js
const cloudinary = require('cloudinary')
const fs = require('fs')
cloudinary.config({
cloud_name: process.env.CLOUD_NAME,
api_key: process.env.CLOUD_API_KEY,
api_secret: process.env.CLOUD_API_SECRET
})
console.log(process.env.api_secret);
const uploadCtrl = {
uploadAvatar: (req, res) => {
try {
const file = req.files.file;
cloudinary.v2.uploader.upload(file.tempFilePath, {
folder: 'avatar', width: 150, height: 150, crop: "fill"
}, async(err, result) => {
if(err) throw err;
removeTmp(file.tempFilePath)
res.json({url: result.secure_url})
})
} catch (err) {
return res.status(500).json({msg: err.message})
}
}
}
const removeTmp = (path) => {
fs.unlink(path, err => {
if(err) throw err
})
}
module.exports = uploadCtrl
Profile.js (Client)
import React, { useState, useEffect } from 'react'
import axios from 'axios'
import { useSelector, useDispatch } from 'react-redux'
import { Link } from 'react-router-dom'
import { isLength, isMatch } from '../../utils/validation/Validation'
import { showSuccessMsg, showErrMsg } from '../../utils/notification/Notification'
import { fetchAllUsers, dispatchGetAllUsers } from '../../../redux/actions/usersAction'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import './profile.css'
const initialState = {
name: '',
password: '',
cf_password: '',
err: '',
success: ''
}
function Profile() {
const auth = useSelector(state => state.auth)
const token = useSelector(state => state.token)
const users = useSelector(state => state.users)
const { user, isAdmin } = auth
const [data, setData] = useState(initialState)
const { name, password, cf_password, err, success } = data
const [avatar, setAvatar] = useState(false)
const [loading, setLoading] = useState(false)
const [callback, setCallback] = useState(false)
const dispatch = useDispatch()
useEffect(() => {
if (isAdmin) {
fetchAllUsers(token).then(res => {
dispatch(dispatchGetAllUsers(res))
})
}
}, [token, isAdmin, dispatch, callback])
const handleChange = e => {
const { name, value } = e.target
setData({ ...data, [name]: value, err: '', success: '' })
}
const changeAvatar = async (e) => {
e.preventDefault()
try {
const file = e.target.files[0]
if (!file) return setData({ ...data, err: "No files were uploaded.", success: '' })
if (file.size > 1024 * 1024)
return setData({ ...data, err: "Size too large.", success: '' })
if (file.type !== 'image/jpeg' && file.type !== 'image/png')
return setData({ ...data, err: "File format is incorrect.", success: '' })
let formData = new FormData()
formData.append('file', file)
setLoading(true)
const res = await axios.post('/api/upload_avatar', formData, {
headers: { 'content-type': 'multipart/form-data', Authorization: token }
})
setLoading(false)
setAvatar(res.data.url)
} catch (err) {
setData({ ...data, err: err.response.data.msg, success: '' })
}
}
const updateInfor = () => {
try {
axios.patch('/user/update', {
name: name ? name : user.name,
avatar: avatar ? avatar : user.avatar
}, {
headers: { Authorization: token }
})
setData({ ...data, err: '', success: "Updated Success!" })
} catch (err) {
setData({ ...data, err: err.response.data.msg, success: '' })
}
}
const updatePassword = () => {
if (isLength(password))
return setData({ ...data, err: "Password must be at least 6 characters.", success: '' })
if (!isMatch(password, cf_password))
return setData({ ...data, err: "Password did not match.", success: '' })
try {
axios.post('/user/reset', { password }, {
headers: { Authorization: token }
})
setData({ ...data, err: '', success: "Updated Success!" })
} catch (err) {
setData({ ...data, err: err.response.data.msg, success: '' })
}
}
const handleUpdate = () => {
if (name || avatar) updateInfor()
if (password) updatePassword()
}
const handleDelete = async (id) => {
try {
if (user._id !== id) {
if (window.confirm("Are you sure you want to delete this account?")) {
setLoading(true)
await axios.delete(`/user/delete/${id}`, {
headers: { Authorization: token }
})
setLoading(false)
setCallback(!callback)
}
}
} catch (err) {
setData({ ...data, err: err.response.data.msg, success: '' })
}
}
return (
<>
<div>
{err && showErrMsg(err)}
{success && showSuccessMsg(success)}
{loading && <h3>Loading.....</h3>}
</div>
<div className="profile_page">
<div className="profile_container">
<div className="col-left">
<h2>{isAdmin ? "Admin Profile" : "User Profile"}</h2>
<div className="avatar">
<img src={avatar ? avatar : user.avatar} alt="" />
<span>
<FontAwesomeIcon icon="fa-solid fa-camera" />
<p>Change</p>
<input type="file" name="file" id="file_up" onChange={changeAvatar} />
</span>
</div>
<div className="form-group">
<label htmlFor="name">Name</label>
<input type="text" name="name" id="name" defaultValue={user.name}
placeholder="Your name" onChange={handleChange} />
</div>
<div className="form-group">
<label htmlFor="email">Email</label>
<input type="email" name="email" id="email" defaultValue={user.email}
placeholder="Your email address" disabled />
</div>
<div className="form-group">
<label htmlFor="password">New Password</label>
<input type="password" name="password" id="password"
placeholder="Your password" value={password} onChange={handleChange} />
</div>
<div className="form-group">
<label htmlFor="cf_password">Confirm New Password</label>
<input type="password" name="cf_password" id="cf_password"
placeholder="Confirm password" value={cf_password} onChange={handleChange} />
</div>
<div>
<em style={{ color: "crimson" }}>
* If you update your password here, you will not be able
to login quickly using google.
</em>
</div>
<button disabled={loading} onClick={handleUpdate}>Update</button>
</div>
</div>
<div className="col-right">
<h2>{isAdmin ? "Users" : ""}</h2>
{isAdmin ?
<div style={{ overflowX: "auto" }}>
<table className="customers">
<thead>
<tr>
<th>ID</th>
<th>Name</th>
<th>Email</th>
<th>Admin</th>
<th>Action</th>
</tr>
</thead>
<tbody>
{
users.map(user => (
<tr key={user._id}>
<td>{user._id}</td>
<td>{user.name}</td>
<td>{user.email}</td>
<td>
{
user.role === 1
? <FontAwesomeIcon icon="fa-solid fa-check" title="Admin" />
: <FontAwesomeIcon icon="fas fa-times" title="User" />
}
</td>
<td>
<Link to={`/edit_user/${user._id}`}>
<FontAwesomeIcon className='adminedit' icon="fas fa-edit" title="Edit" />
</Link>
<FontAwesomeIcon className='admindelete' icon="fa-solid fa-trash-can" title="Remove"
onClick={() => handleDelete(user._id)} />
</td>
</tr>
))
}
</tbody>
</table>
</div> : ""}
</div>
</div>
</>
)
}
export default Profile
Here is my posts multer image in server.js
app.use('/', express.static('uploads'));
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
