I´m building an app with NodeJs and Angular
The server runs on http://localhost:9000
And the app runs on http://localhost:4200
I have an endpoint whose looks like this http://localhost:9000/users
I use this to retrive all users
The set returned has a key like this { photo: myphoto.jpg }
When I loop the set of data, I want to render the image as this way
<img src="{{ url }}/uploads/users/{{ user.photo }}" alt="{{ user.name }} {{ user.last_name }}"
class="img-fluid shadow-sm avatar100 ml-auto mr-auto d-block rounded-circle">
Where url is http://localhost:9000 and user.photo is myphoto.jpg
The complete route is http://localhost:9000/uploads/users/myfoto.jpg
There is the photo hosted, but the server is throwing an error
Cannot GET /uploads/users/myfoto.jpg
I think, the server is interpreting the URL as API route, and obviously is not declared on routes file.
I want to only retrive the image, how could I do that?
I don´t know what part of my code I can show here. Routes? Front-end? Project structure? Tell me what do you need
With Express, you have to create a route that will handle your image URLs. By default, Express (or the built-in node.js web server) does not serve ANY files. So, it will only serve a file if you create a handler for that specific URL and program that handler to deliver the desired file.
If your images are directly in the file system where the URL base filename matches the actual filename in your server file system, you could use express.static() to create a single route that would serve all your images.
For example, you could use express.static like this:
app.use("/uploads/users", express.static("/uploads/users"));
This would allow a URL requested from:
http://localhost:9000/uploads/users/myphoto.jpg
to be automatically served from the server-side file system at
/uploads/users/myphoto.jpg
It would similarly work for any other matching name in that same directory (or even sub-directories of that directory if the sub-directory was also in the URL).
In general, you don't want to surface internal path names such as /uploads/users all the way back to the user's HTML pages. So, you could do this instead in the HTML page:
<img src="/images/myphoto.jpg">
And, this on the server:
app.use("/images", express.static("/uploads/users"));
This will take any http requests that start with a path of /images and look for the matching filename in /uploads/users on the server, thus not exposing the internals of your server directory structure to the client. It creates the notion of an abstract /images URL that your server can then process and get the images from wherever they happen to be stored on the server.
$ npm i multer
and server add
app.use("/public", express.static("public")); //The folder where the file is located
Related
So my question is about the URL as filesystem against the new web approach of NODEJS+EXPRESS and REACT.
lets assume that we have in the root directory '/' the following files:
root '/' directory:
index.html
image_super.jpg
images_secret '/images_secret' directory:
image1.png
image2.png
image3.png
image4.png
so we can approach to the files in the filesystem in the following way:
www.localhost:3000/index.html -> will get us the the index.html html form (as plaint text)
www.localhost:3000/image_super.jpg -> will get us the image_super.jpg in the root directory
www.localhost:3000/images_secret/image3.png -> will get us the image3.png inside the directory images_secret
and so on...
what i'm trying to point that it's acting just like a file system! we're sending an HTTP 1.1 '/' GET request or HTTP 1.1 '/index.html' GET or HTTP 1.1 '/images_secret/image3.png' GET and it will get us the content right out our server file system.
just to mention - due to this filesystem URL we have LFI vulnerability that includes path traversal (that we can /../ go back and get out from the root directory)
and my confusion is:
in NODEJS+EXPRESS we have middleware that treats our URL request not as filesystem we're treating our URL requests as Route middleware - for example we want to get /users for the URL it will use the Route middleware such as app.route('/users', getUsers) or somthing.
so my question is:
why when we're using NODEJS+EXPRESS it's not acting just like a filesystem? how does it possible that we use the URL as filesystem in one hand, and make it in the other hand a virtual URL that is not getting reall files?
same for react, i know that react is rendering the DOM objects in one HTML file SPA, but the URL is "virtual" there too.
Thanks!
URL to be one thing and not 2 different things, filesystem and as virtual abstract requests...
I have a Node.js backend that sends an icon image to a React frontend. Initially, I encode this image as a Base64 string and store it directly in the database. I created an api that returns this string to the frontend. However, I read that it is bad to store it in the database, so I re-wrote the api to store this string in the server as a json file and now my api returns the absolute path to this json file. However, how is the React frontend supposed to retrieve the file? Is it possible to use the absolute path or do I have to create another api to return a file object ? If so, how do I do that?
I'm a newbie at both react and node.js so any help is appreciated.Thanks.
EDIT: I stored the file path as __dirname of where my code resides + filename.I'm getting cors error when accessing that url
Use Express to share out that folder as such-and-such.
Suppose you keep your files in a folder called files, just off the root. And suppose your server structure looks roughly like this:
- backend
- app.js
- frontend
- Components
- Routes
- public
- dev
- index.html (your template file)
- files
- myimage.png
In your root js file (app.js? server.js? index.js?):
const app = express()
app.use('/static', express.static('public'));
app.use('/files', express.static('public/files'));
Then, in the frontend code:
<img src='/files/myimage.png' />
By the way, there is no problem storing images as base64 in your database... but every database backup will also backup those images. If you have a small database, no worries. However, if you have a LOT of images, especially very large images, this will make your database (and backups) unnecessarily large and unwieldy.
Everything depends on your use case.
I'm running my react client on localhost:3000 and my express server on localhost:4000, and I have a static folder in my server with images.
I'm trying to save the image path to a MySQL database, and use that in React as an img src, but can't figure out how to do it without hard coding the path. For example, localhost:4000/images/img1.jpg works, but if I change the host name tomorrow, all of my db data becomes irrelevant.
Three answers:
In react you can fill props by joining a constant string and a variable. Just save the /images/img1.jpg in the database instead of full URL. Then in react do <img src={'http://localhost:4000/' + imagePathFromDB} />. When you change the server just change it once.
You can create a simple SQL query to update your DB to be relevant this is the beauty of SQL database.
For e.g.
update images set path=replace(path,'localhost:4000','newdomain.com')
Voilla!
If you using create-react-app you can serve the frontend and backend from the same domain using the proxy parameter. And then just save in the database /myimage.jpg and in React <img src={myVariable} />
I'm wanting to set the static path with node.js in app.js.
Such as the follow with setting in the public folder:
app.use(express.static(path.join(__dirname, 'public')));
When I use template engines, such as mustache https://mustache.github.io/,
you can set it using a relative path in the template to get a photo a.jpg, like:
<img src="./a.jpg">
When I save a user's photo in the public folder.
In Angular, how do I set the img url relative path from the node.js server folder.
If I save the the full URL in the DB and set the URL in img:
http://120.8.12.8:3000/a.jpg
//or
http://domainname:3000/a.jpg
html:
<img src="http://120.8.12.8:3000/a.jpg">
<img src="http://domainname:3000/a.jpg">
When I change the IP or domain name, the URL will fail.
How can I set it?
I would not save the full path in the database.
Otherwise, I will save information about how to generate the path.
You can have 2 fields in the database, like:
{
"relativePath" : "a.jpg",
"server" : "http://120.8.12.8:3000"
}
After this, and assuming you are consuming the resource from angular, you have several options:
You can directly mix the relativePath and the server in the frontend and create the URL to place in the link
You can hardcode in your angular app what is the "server", and mix that with the relativePath. In this case, in case you migrate the images you just need to modify the frontend
(The best for me). Create an endpoint in the server which gives you what is the host of the image server, call it from your angular app and then create the full link with this response and the relative image path.
I have a expressJs setup which looks like this:
// Imports...
const app: express.Application = express();
const port: number = 3001;
const listener = new StatementListenerAPI();
app.use('/listen', listener.getRouter());
app.use('/welcome', router);
if (fs.existsSync('./client')) {
// Running in prod environment with pre built client directory. Serve this.
app.use(express.static('./client'));
}
app.listen(port);
So I have some routers connected to the express app, and at the bottom I declare that the directory client should be served statically. This directory contains an index.html as well as lots of JS, CSS and PNG files. However, no matter which URL I try to access from the express server, it always shows the code of the index.html within the statically served directory. The references to the JS and CSS files used inside the index.html also just return the code of the index.html.
I am using ExpressJS 4.16.3
What am I doing wrong?
Edit: So technically it works if using __dirname + '/client' instead of ./client. What I am now getting is that, when making GET requests from e.g. Postman (therefore "hand-crafting" the HTTP requests), I am always getting the correct results. If I call the resources from within my web browser, it still always shows the website (resolves the index.html). However, now all resources like JS and CSS scripts are being resolved properly, so apperantly Chrome resolves those dependencies properly, I am just wondering why I am still getting the contents of index.html as result when requesting some of the assets or some of the express endpoints via Chrome. API calls via code are working fine, so its only why manual chrome requests show this weird behaviour, at this point I am only asking out of curiosity.
Answer to your original question:
The path supplied to express.static should be relative to the directory from where you launch your node process or an absolute path. To be safe construct an absolute path (ie from the current directory or file). For example:
app.use(express.static(__dirname + '/client'));
Regarding your followup question:
I assume this is because Chrome uses heavy caching and it thinks this folder should return the html file. You can try and reset all caches in Chrome, or just for the page.