I am hosting React app on Netlify and NodeJs server on Heroku.
The image is hosted on the server directory, in an "image" folder..
// Build the image path
const file = req.file ?
req.protocol + '://' + req.get('host') + '/' + req.file.path
: null;
The code above is building the image link which will be stored in the database and will be looking like "https://home-renter.heroku.com/images/1663093729973.jpg". Normally, if I paste the link on the browser, the server should send the image...
But in this case I get 404 error....
The image link is saved into the mongodb as
In the chrome console I have the following errors and warnings:
I do not know what should I look for. I dont have a starting point...
Update. If I add a house, and upload images, the image selection works. However if I refresh the page, the website crashes and send 404...
// Static files
const path = require('path')
app.use('/images', express.static(path.join(__dirname, 'images')));
app.get('/', (req, res, next) => res.send('Wellcome to home renter'));
Update
The problem was while I was deleting the images from the post. I was splitting the image link from 3000 (port) instead of the new URL.
Related
Sorry in advance for my lengthy post.
I am having difficulty changing from MERN localhost to an online hosting. I've been hosting my frontend/ client side website on heroku, with the file structure as follows:
Client Structure
- build
- src
- App.js
- Index.js
- Other Components, Images, Fonts, Pages
-package.json
-package-lock.json
This file structure works fine with heroku.
However, I've been following a Youtube tutorial that uses a MERN stack to build a blog: https://www.youtube.com/watch?v=OML9f6LXUUs&t=3s --> it is a 3 part series
In the video, he has a file structure as such:
API and Client Structure
- api
- images
- models
- public
- routes
- index.js
- package.json
- package-lock.json
- client (frontend code)
- build
- src
- App.js
- Index.js
- Other Components, Images, Fonts, Pages
-package.json
-package-lock.json
2 Instances of LocalHost
He runs api on localhost:3001 and client on localhost:3000.
Methodology
1. Storing Images
He does not store images in MongoDB cloud, but rather store the image name only, and stores the images directly on the api/images directory.
In the api folder, he uses multer to store the images.
app.use("/images", express.static(path.join(__dirname, "/images")))
const storage = multer.diskStorage({
destination: (request, file, callback) => {
callback(null, 'images');
},
filename: (request, file ,callback) => {
callback(null, request.body.name);
},
})
const upload = multer({storage: storage});
app.post('/api/upload', upload.single('file'), (request, response) => {
response.status(200).json('File has been uploaded');
});
Then in the client side, he sends the data via axios:
const response = await axios.post('/upload', data);
2. Retrieving Images
When retrieving, he specifies a public folder PF, uses axios to get the image name, and then concatenates them to get the images.
const PF = "http://localhost:3001/images/";
<Image src={PF + post.image} />
My question is:
How can I change from a localhost to a cloud based hosting (preferably Heroku)? What paths do I specify? I would think that this image retrieval works because I am running both locally on the same computer. I wouldn't be able to use it if they are online as the image src directory will not be searchable
Is it possible to host both simultaneously on 1 Heroku Dyno, and how can I do it?
This is my first time learning backend so thanks for the patience!
Firstly, you'll have to remove all hardcoded 'http://localhost:3000`. This would interfere with the cloud site since it uses its own.
Instead, you could use an environment file to store the API site and in production use a different one.
You will need to make a mongodb cluster (its a cloud database and its free) https://www.mongodb.com/docs/atlas/tutorial/create-new-cluster/. You'll have to manually change your database to the cluster link. I would use an environment variable for this as well, so the db link would be something like this in your db file
const mongoURI = process.env.MONGODB_URI || 'mongodb://localhost:27017/ProjectAPI'
where process.env.mongodb_uri contains cluster uri
In the server file where you host your routes add this to the end of your file and change to match your app:
app.use(express.static(__dirname + "/../client/build"));
app.get("*", (req, res) => {
// check for page routes that we expect in the frontend to provide correct status code.
const goodPageRoutes = ["/", "/login", "/home"];
if (!goodPageRoutes.includes(req.url)) {
// if url not in expected page routes, set status to 404.
res.status(404);
}
// send index.html
res.sendFile(__dirname + "/../client/build/index.html");
});
After that just follow the guide: https://devcenter.heroku.com/articles/git and https://devcenter.heroku.com/articles/deploying-nodejs
I created a node server public/image folder to store my image file uploads. I can upload to the folder and store the url in the postgresql table with that users id with no problem. However, when I fetch that image url from the the database, I get the url but the browser always says "cannot get /...". Im using react to fetch the json response and add the image url property to the src in an avatar. Please help. I don't understand why. I'm using the app.use middelware below:
app.use(express.static('public')) app.use('/images', express.static('images'))
This is the image in the folder:
This is the avatar where I add the src props.
Here is the URL inside the browser react tools
in case you're getting a CORS error, you should use this:
var cors = require('cors')
const app = express()
app.use(cors())
app.use(express.static('public'));
you can access it with you're specified port:
http://localhost:PORT/filenameWithExtension
I'm just a little confused on how to serve the assets correctly from the source folder.
Relevant server-side code (The client makes a request to /images, the server sends back the file names):
const images = './static/images/';
app.use(express.static('static/images'))
app.get('/images', (req, res) => {
res.setHeader('Content-Type', 'application/json');
fs.readdir(images, (err, files) => {
res.send(files);
});
});
My directory structure looks like this:
public
index.html
server (houses Node/Express code)
index.js
src (houses React code)
App.js
static
images
image1, image2, image4, image4
If I try to display the image in React (state.currImage being one of the 4 file names):
<img alt="scan" src={ require(this.state.currImage)}
I get an error saying "Unhandled Rejection (Error): Cannot find module './static/images/file1.jpg'"
It looks like you could maybe remove the require from the image loading considering it's a path to an image and not a path to a javascript module.
<img alt="scan" src={this.state.currImage}
You may need to update the url of those images to point to the server url. Right now the string is ./static/images/file1.jpg but it may need to be /images/file1.jpg.
I just decided to use NodeMailer and it works well on localhost, but on the server, I don't know which path should I go to find the page's link. so here is the path in the app.js
// Static folder
app.use("/", express.static(path.join(__dirname, "/views")));
// Body Parser Middleware
app.use(bodyParser.urlencoded({extended:false}));
app.use(bodyParser.json());
app.get("/views", (req,res) =>{
res.render("contact");
});
and in the views folder, I have the file contact.handlebars
I tried on the live server this links to find my web-form
mywebsite/views/contact.handlebars (this is downloading the file)
mywebsite/views/ (this shows just the index of the views)
enter image description here
mywebsite/views/contact ( nothing )
Again, on my localhost, Everything works very well (localhost:3000/views)
I will be appreciated if someone would help me with this issue.
I am new to nodeJS server area, need help in understanding how to work with REST API (using express) and deploy the angular application over a singe node server and same ports.
By deploying i want to understand if user hit below url http://localhost:8000/<page_name> then the specified page should open.
And is user hit below url using get or post request
http://localhost:8000/api/<api_name> then a json or a text will be returned.
How to run both the thing over a single node server.
Lets assume, you have all your static files in the /public folder of you app. Generally spoken, if you are using express.static, you should also get your index.html because this is handled by default for each directory.
In your case, as you are using Angular, the routing is handled from the client side (SPA). You should only have one single index.html after building your Angular app. All files from your dist folder should then be placed into your /public folder. Then you need to make sure, that initial file serving provides your index.html like so:
In this example static files are served first, then your API and if nothing is found, you are getting back you index file.
const express = require('express');
const app = express();
// serve static files
app.static(__dirname + '/public'));
// serve your API
app.get('/api/welcome', function (req, res) {
res.send('Welcome');
});
// fallback routing (server side handling)
app.get(/.*/, function (req, res) {
res.sendFile(__dirname + ‘/public/index.html‘
});
app.listen(3000);
Next time please make sure, to give all necessary information in your question ;-)
With the help from Sebastian, so far I can find a solution but its not working when i am hitting URL for different pages.
const express = require('express');
const app = express();
app.use(express.static('public'))
Please provide your suggestions.