return the path of an image that is hosted on my server to show it on the fron-end - node.js

currently on my server I have under the path theses images:
/opt/myproject/assets/5259521.jpg
/opt/myproject/assets/5259522.jpg
/opt/myproject/assets/5259523.jpg
I am using nodejs to create my web services. I want to know what is the way to return the path of my images so that the front-end can show them in an img tag.
my restAPI can be accessed by a path:
http://3.89.xx.xx/getImages
Here I would need to return the image paths so that I can display them in my web application.
app.use(cors());
app.options('*', cors());
// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: false }))
// parse application/json
app.use(bodyParser.json());
// Configuración global de rutas
app.use(require('./routes/index'));
const distDirectory = path.join(__dirname, '/public');
app.get('*', function (req, res, next) {
const file_path = path.join(distDirectory, req.url.split('?').shift());
if (fs.existsSync(file_path)) next();
else res.sendFile(path.join(distDirectory, 'index.html'));
});
app.use(express.static(distDirectory));
thanks

To serve static files such as images, CSS files, and JavaScript files, use the express.static built-in middleware function in Express.
The function signature is:
express.static(root, [options])
You need to put all you images in public folder or add the folder name of you choice and then pass the static folder in the express.static middleware.
The name of the folder Public is just a convention, you can set name of folder to anything.
For example, use the following code to serve images, CSS files, and JavaScript files in a directory named public:
app.use(express.static('public'))
And access it like :
http://localhost:3000/assets/5259521.jpg
I am assuming that you the images are under public/assets folder.

To use the static files in Node js
There is a path called 'public' which holds all the files CSS, Bootstrap, Images etc.
add this line to the code
app.use(express.static("public")
if the structure of public folder is
-public
-css
-picture
-images
then you have use images for frontend
<img src = "picture/a.png">
<img src = "image/b.png">
<img src = "image/c.png">
you can have many folders in public folder

Related

Node express app.get("/.." parent directory not working

./core/server.js
./core/index.html
./core/styles.css
./bin/init-transpiled.js
How can I host index.html at localhost:8000 (not /core) where index.html still has access to relative paths ../bin/init-transpiled and ./styles.css?
You can host your index.html file like this.
app.get('/', function(req, res) {
res.sendFile(path.resolve(__dirname + "/index.html"));
});
And you need to set bin folder as static folder in your server configuration to access bin folder files from client side.
app.use(express.static(path.resolve(__dirname + '/../bin')));
Then in index.html you can access your file like this.
<script src="../bin/init-transpiled.js">
Note that if index uses ./styles.css for example, you would need to use ../core/styles.css
app.use('/', express.static(__dirname));
app.use('/', express.static(__dirname + '/../'));
app.get('/', function (req, res) {
res.sendFile(__dirname + "/index.html");
});
When '/' is used,
statically host this dir (for accessing local ./styles.css for example)
statically host the parent dir (otherwise you can't traverse through ../bin/)
send index.html as a response.
Note: '/' is not required, the default is '/' and you can just write your middleware handler function as the first param
See Express Docs - static files

Exclude sub directory from static files in express

Is there any way to exclude sub directory from express static middleware in express 4.8.5.
For example if I have :
app.use(express.static(__dirname + 'public'));
And my public directory is like this :
- public
- css
- images
- scripts
- index.html
- exclude_me
- scripts
- views
- index.html
So I need to exclude last sub directory and when user does :
GET /exclude_me
It should call my route rather than returning directory automatically.
I can't just remove it from public dir because it depends on stuff inside it because public directory is angular application and exclude_me is another angular application that fetches scripts from /exclude_me/scripts AND from /public/scripts.
I know it is little confusing but it is how it is and I cannot just remove it from public dir because it won't see public/scripts any more which are needed and I cannot leave it because I cannot authorize it then (all authorization is in public/scripts)
If there is some smarter way to do this, feel free to let me know :)
You can add your own middleware. Here's what I did to exclude some folders:
app.use('/public', (req, res, next) => {
if (env !== 'development') {
var result = req.url.match(/^\/js\/(maps|src)\/.+\.js$/)
if (result) {
return res.status(403).end('403 Forbidden')
}
}
next()
})
app.use('/public', express.static(path.join(__dirname, '/public')))
It's possible by adding regular expressions to the first optional param of use method.
According with Express 4.x API path documentation.
Example, I don't want to give access to my secure folder inside public folder:
var express = require('express');
var app = express();
app.use([/^\/public\/secure($|\/)/, '/public'], express.static(__dirname + '/public'));
This will allow you to access all files but not the ones in the secure folder.
You can use it also to restrict a file extension, example files that ends with .js.map:
app.use([/(.*)\.js\.map$/, '/public'], express.static(__dirname + '/public'));
And you also can add multiple rules, like this example where secure folder and files that end with .js.map are ignored from the static folder:
app.use([/^\/public\/secure($|\/)/, /(.*)\.js\.map$/, '/public'], express.static(__dirname + '/public'));
I had a similar problem, which may be the answer you were seeking. Given the following directory:
public
css/
images/
secure/
index.html
The Express Middleware stack I wanted was this:
1. Static files (except the `secure/` directory)
2. Logging
3. Authentication
4. `secure/` static files
Here's how I solved it:
var express = require('express');
var path = require('path');
var app = express();
// path.join here makes it work cross platform with Windows / Linux / etc
var statics = express.static(path.join(__dirname, 'public'));
function secureStatic(secure) {
return function (req, res, next) {
if (/^\/secure/.test(req.path) === !!secure) return statics(req, res, next);
return next();
};
}
// add public files
app.use(secureStatic());
app.use(logging());
app.use(authentication());
// add secured files
app.use(secureStatic(true));
This will only serve public files when unauthenticated, and only serve secure files after authentication.
Most solutions above are to use a middleware.
However, there is a just easier way to solve this.
Don't serve static assests directly with the dir public rather than serve dir just what you want to serve with a virtual path prefix .
You can serve like below
var express = require('express');
var app = express();
app.use('/public', __dirname + 'css');
app.use('/public', __dirname + 'images');
...

Render views and partials from multiple directories with Dust and Express

I'm wiriting a very complex CMS with Node, Express and Dust with Consolidate.
The CMS have Modules and Widgets:
Modules are things that respond to routes and render pages
Widgets are fragments of these pages.
The problem is that each Module and Widget have your own views folder and Express only allows you to set one "views directory", and in the Dust docs I couldn't even find in which directory Dust looks up for templates.
My folder structure look like this:
root
modules
module-1
module-n
module-n-controller.js
module-n-routes.js
module-n-view.dust
widgets
widget-1
widget-n
widget-n-controller.js
widget-n-routes.js
widget-n-view.dust
So, module-n-controller.js does something like this:
// just pretend that this data came from the widget-n-controller.js
var data = {
"widget" : {
"view": "./widgets/widget-n/widget-n-view",
"data": widgetNData
}
}
res.render('./modules/module-n/module-n-view', data);
Then, in my module-n-view.dust, I want to do something like this:
{#widget}
{>"{view}" data=data/}
{/widget}
So the question is: How do I set the path to these views, and, is res.render the right method to do this or should I use dust.render?
PS: I tried dust.render and I got "Error, can't find template" with every variation of the path.
STEP 1
root/app.js
var app = require("express")(),
cons = require("consolidate");
// Do this to get DustJS rendering .html files
// So, in the file structure above, you can rename the views extensions from .dust to .html
app.engine('html', cons.dust);
app.set('view engine', 'html');
// Set the views directory to the root directory of the application
// This way you can access views into any directory inside your application
app.set('views', '.');
root/widgets/widget-n/widget-n-controller.js
module.exports.index = function (req, res, next) {
return {
"widget" : {
"view": __dirname + '/widget-n-view',
"data": widgetNDataFromDB()
}
};
}
root/modules/module-n/module-n-controller.js
module.exports.index = function(req, res, next){
var data = require("../../widgets/widget-n/widget-n-controller").index(req, res, next);
res.render(__dirname +'/module-n-view', data);
}
STEP 2 - VERY IMPORTANT FOR .HTML FILES!
This is necessary to get consolidate looking up for .html files when rendering partials.
I don't know why but, when rendering partials, consolidate seems to look up only .dust files, even if you have specified html as the app and view engine.
Skip this if you're using the .dust extension.
node_modules/consolidate/lib/consolidate.js
Search for this function:
exports.dust.render
Inside of this function you'll find the following:
var ext = 'dust'
, views = '.';
Just change it to:
var ext = 'html'
, views = '.';
It was really hard to figure it out... I really hope it helps somebody else out there.

How to serve rendered Jade pages as if they were static HTML pages in Node Express?

Usually you render a Jade page in a route like this:
app.get('/page', function(req, res, next){
res.render('page.jade');
});
But I want to serve all Jade pages (automatically rendered), just like how one would serve static HTML
app.use(express.static('public'))
Is there a way to do something similar for Jade?
"static" means sending existing files unchanged directly from disk to the browser. Jade can be served this way but that is pretty unusual. Usually you want to render jade to HTML on the server which by definition is not "static", it's dynamic. You do it like this:
app.get('/home', function (req, res) {
res.render('home'); // will render home.jade and send the HTML
});
If you want to serve the jade itself for rendering in the browser, just reference it directly in the url when loading it into the browser like:
$.get('/index.jade', function (jade) {
//...
});
https://github.com/runk/connect-jade-static
Usage
Assume the following structure of your project:
/views
/partials
/file.jade
Let's make jade files from /views/partials web accessable:
var jadeStatic = require('connect-jade-static');
app = express();
app.configure(function() {
app.use(jadeStatic({
baseDir: path.join(__dirname, '/views/partials'),
baseUrl: '/partials',
jade: { pretty: true }
}));
});
Now, if you start your web server and request /views/partials/file.html in browser you
should be able see the compiled jade template.
Connect-jade-static is good, but not the perfect solution for me.
To begin with, here are the reasons why I needed jade:
My app is a single page app, there are no HTMLs generated from templates at runtime. Yet, I am using jade to generate HTML files because:
Mixins: lots of repeated / similar code in my HTML is shortened by the use of mixins
Dropdowns: I know, lots of people use ng-repeat to fill the options in a select box. This is a waste of CPU when the list is static, e.g., list of countries. The right thing to do is have the select options filled in within the HTML or partial. But then, a long list of options makes the HTML / jade hard to read. Also, very likely, the list of countries is already available elsewhere, and it doesn’t make sense to duplicate this list.
So, I decided to generate most of my HTML partials using jade at build time. But, this became a pain during development, because of the need to re-build HTMLs when the jade file changes. Yes, I could have used connect-jade-static, but I really don’t want to generate the HTMLs at run time — they are indeed static files.
So, this is what I did:
Added a 'use' before the usual use of express.static
Within this, I check for the timestamps of jade and the corresponding html file
If the jade file is newer, regenerate the html file
Call next() after the regeneration, or immediately, if regeneration is not required.
next() will fall-through to express.static, where the generated HTML will be served
Wrap the ‘use’ around a “if !production” condition, and in the build scripts, generate all the HTML files required.
This way, I can also use all the goodies express.static (like custom headers) provides and still use jade to generate these.
Some code snippets:
var express = require('express');
var fs = require('fs')
var jade = require('jade');
var urlutil = require('url');
var pathutil = require('path');
var countries = require('./countries.js');
var staticDir = 'static'; // really static files like .css and .js
var staticGenDir = 'static.gen'; // generated static files, like .html
var staticSrcDir = 'static.src'; // source for generated static files, .jade
if (process.argv[2] != 'prod') {
app.use(‘/static', function(req, res, next) {
var u = urlutil.parse(req.url);
if (pathutil.extname(u.pathname) == '.html') {
var basename = u.pathname.split('.')[0];
var htmlFile = staticGenDir + basename + '.html';
var jadeFile = staticSrcDir + basename + '.jade';
var hstat = fs.existsSync(htmlFile) ? fs.statSync(htmlFile) : null;
var jstat = fs.existsSync(jadeFile) ? fs.statSync(jadeFile) : null;
if ( jstat && (!hstat || (jstat.mtime.getTime() > hstat.mtime.getTime())) ) {
var out = jade.renderFile(jadeFile, {pretty: true, countries: countries});
fs.writeFile(htmlFile, out, function() {
next();
});
} else {
next();
}
} else {
next();
}
});
}
app.use('/static', express.static(staticDir)); // serve files from really static if exists
app.use('/static', express.static(staticGenDir)); // if not, look in generated static dir
In reality, I have a js file containing not just countries, but various other lists shared between node, javascript and jade.
Hope this helps someone looking for an alternative.

express + stylus + jade, nothing gets compiled

I cannot get this simple app.js to work: static files are served but jade and styl files are not compiled.
Here the __dirname ls:
damianomacbook:www damiano$ ls
app.jade app.js app.styl config.xml johnd.jpg
.jade and .styl files are served normally and plain.
Here what happens when curling css and html files (which the middlewares functions are supposed to generate on the fly):
damianomacbook:www damiano$ curl localhost:8080/app.css
curl: (52) Empty reply from server
damianomacbook:www damiano$ curl localhost:8080/app.html
Cannot GET /app.html
What's missing?
Guilty code:
var express = require('express');
var stylus = require('stylus');
var nib = require('nib');
var app = express();
function compile(str, path) {
return
stylus(str)
.set('filename', path)
.use(nib());
}
app.use(express.logger('dev'));
app.set('views', __dirname);
app.set('view engine', 'jade');
app.use(stylus.middleware({
src: __dirname,
compile: compile
}));
app.use(express.static(__dirname));
app.listen(8080);
Your GET /app.html is failing because serving HTML pages is done with the express router, not middleware, and you don't have any routes defined. The static middleware doesn't convert anything (thus the name), so it's not going to serve /app.html unless there's an actual app.html file on disk. To get /app.html working, add:
app.get('/app.html', function (req, res) { res.render('app');});
//or you probably want app.get('/', ...if you want this to be your home page
//you probably also don't want/need ".html" in your URLs as this has fallen out of style
Your stylus problem is the automatic semicolon insertion monster. You must not put the "return" keyword on a line by itself. Your compile function is returning undefined instead of a stylus instance. Keep the compile formatted as it is on the nib documentation and all is well.

Resources