'Uploading Images using Multer (works locally, but not when deployed on Heroku)
I'm a bit stuck with my blog app.
It works properly when I run it locally, but when it's deployed to Heroku it seems that the images that get uploaded via Multer aren't being uploaded into my images folder
When I create a post from the Heroku app, I can create the post - but the picture is missing
Below is my server code
const path = require("path");
const db = require('./config/connection');
const multer = require('multer')
const routes = require('./routes');
const app = express()
const PORT = process.env.PORT || 5000
app.use(express.urlencoded({ extended: true }));
app.use(express.json())
app.use("/images", express.static(path.join(__dirname, "./images")));
const storage = multer.diskStorage({
destination: (req, file, callback) => {
callback(null, 'images')
},
filename: (req, file, callback) => {
callback(null, req.body.name)
}
})
const upload = multer({ storage: storage })
app.post('/upload', upload.single('file'), (req, res) => {
res.status(200).json('File has been uploaded')
})
if (process.env.NODE_ENV === 'production') {
app.use(express.static("client/build"));
}
app.use(routes)
db.once('open', () => {
app.listen(PORT, () => {
console.log(`API server running on port ${PORT}!`);
});
});
Below here is my client code
import React, { useContext, useState } from 'react';
import './write.css';
import { Context } from '../../context/Context';
export default function Write() {
const [title, setTitle] = useState('')
const [description, setDescription] = useState('')
const [file, setFile] = useState('')
const { user } = useContext(Context)
const handleSubmit = async (e) => {
e.preventDefault()
const newPost = {
username: user.username,
title,
description,
}
if(file){
const data = new FormData()
const filename = Date.now() + file.name
data.append('name', filename)
data.append('file', file)
newPost.postPicture = filename
try {
await axios.post('/upload', data)
} catch (error) {
console.log(error)
}
}
try {
const response = await axios.post('/posts', newPost)
window.location.replace('/posts/'+response.data._id)
} catch (error) {
console.log(error)
}
}
return (
<div className='write'>
{file &&
<img
className='write_image'
src={URL.createObjectURL(file)}
alt=""
/>
}
<form className='write_form' onSubmit={handleSubmit}>
<div className='write_form_group'>
<label htmlFor='file_input'>
<i className='write_icon far fa-plus-square'></i>
</label>
<input type='file' id='file_input' style={{display: 'none'}} onChange={e=>setFile(e.target.files[0])} />
<input type='text' placeholder='Title' className='write_input' onChange={e=>setTitle(e.target.value)}/>
</div>
<div className="write_form_group">
<textarea placeholder='Tell your story...' type='text' className='write_input write_text' onChange={e=>setDescription(e.target.value)}></textarea>
</div>
<button className='write_submit' type='submit'>Publish</button>
</form>
</div>
)
}
I'm not sure what's going wrong, my brain is being pointed into the server side code where I use multer.diskStorage (maybe this doesn't work when the app is being hosted somewhere?)
Any advice would be amazing
Also here is the link to the whole repo on my github... because I feel like just looking at the code in these posts might be hard to follow
Solution 1:[1]
Heroku doesn't let you do this. You need to create a bucket on Amazon's S3 service or another similar service to upload that.
Solution 2:[2]
You may also use cloudinary its easy to use also a free service.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | galih wisnuaji |
Solution 2 | Andrew Aghoghovwia |