Can't access images in upload folder using Express and multer - angularjs

I have an application built on Node/Express/Angular.
I have all my angular front end code in a "client" folder and I have all my backend (nodejs & express) in another folder ("server").
I use Grunt to compile the code into the "server/dist" folder, so when I publish to production, I'm just uploading the "server" folder.
I've added a feature to upload images and am using multer to do that.
I've created an "fileuploads" folder in the "server" directory and am successfully uploading files to that folder.
The Problem:
In my app I need to reference the images, but even though I've created a static reference in my server/app.js file, I'm still unable to reach them.
Here is what my server side app.js file looks like:
var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var mongoose = require('mongoose');
var cors = require('cors');
var multer = require('multer');
mongoose.connect('mongodb://localhost/OM');
var app = express();
// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(cookieParser());
app.use(cors());
app.use('/api', require('./routes/api'));
app.use('/sendmail', require('./routes/sendmail'));
app.use('/uploads', require('./routes/uploads'));
app.use(express.static(path.join(__dirname, '../client/app/custom')));
app.use(express.static(path.join(__dirname, '/dist')));
app.use(express.static(path.join(__dirname, '/fileuploads')));
// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: {}
});
});
app.all('/*', function(req, res){
res.sendFile(path.join(__dirname, '/dist/index.html'));
});
module.exports = app;
On the client side, I've tried accessing the files in the following way:
<img src="fileuploads/0d904f4a422ea5a8fcd9a3859b58cdb9" />
<img src="/fileuploads/0d904f4a422ea5a8fcd9a3859b58cdb9" />
<img src="../fileuploads/0d904f4a422ea5a8fcd9a3859b58cdb9" />
But nothing seems to work.
What am I missing?

It will be nice to have
app.use(express.static(path.join(__dirname, '/fileuploads')));
as
app.use('/fileuploads', express.static(path.join(__dirname, '/fileuploads')));
or make it shorter this way:
app.use('/fileuploads', express.static(process.cwd() + '/fileuploads'));
That way, you will be able to access it anywhere in your app as:
<img src="/fileuploads/0d904f4a422ea5a8fcd9a3859b58cdb9" /> which is basically saying "anywhere i call fileuploads, serve me the right path". ^_^

Related

MEAN application setup doesn't redirect routes to Angular application

I am trying to setup a base for a MEAN application. I created the new project using Angular CLI, added Express.js, MongoDB modules to the application. In the app.js file I have the following configuration:
var express = require('express');
var bodyParser = require('body-parser');
var session = require('express-session');
var path = require("path")
var app = express();
var conf = require('./config/conf');
var server = require('http').Server(app);
var mongoDB = require('./adapters/mongodb')
var mongoClient = new mongoDB(conf);
app.use(bodyParser());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.get('*', (req, res) => {
res.sendFile(path.join(__dirname, 'dist/index.html'));
});
app.use(function (req, res, next) {
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type,__setXHR_');
res.setHeader('Access-Control-Allow-Credentials', true);
next();
});
mongoClient.connect(function (dbconn) {
app.dbconn = dbconn;
app.conf = conf;
console.log("************************************************************");
console.log(new Date() + ' | CRUD Server Listening on ' + conf['web']['port']);
console.log("************************************************************");
server.listen(conf['web']['port']);
var Routes = require('./routes/http-routes');
new Routes(app);
});
I setup a hello world route for now and no changes done to the angular sources, which means I would land at the Angular default starting page. But I cant land at the page but instead a white screen page. However, I can access the routes using Postman. I do ng build and then node app.js to run the application. What am I doing wrong?
You should use the Express way to handle routes
First
const router=express.Router();
Then let's suppose you have a file using only authentication routes
const authentication = require('./routes/authentication')(router);
To conclude, you only have to do :
app.use('/authentication', authentication);
This allows a better divison of your routes
You 'll use your routes this way
module.exports= (router)=>{
router.get('/',(req,res)=>{
res.json(message:'Hello World');
});
return router;
To set angular routes you need the router module, for more details read the documentation
You serve only index.html from your Angular App. But you need also serve assets, css and javascript. Easiest would be something like this (but you need to adjust directory names:
app.use('/js', express.static(path.resolve(__dirname, 'dist/js')));
app.use('/css', express.static(path.resolve(__dirname, 'dist/css')));
app.use('/assets', express.static(path.resolve(__dirname, 'dist/assets')));

Nodejs: Failed to lookup view "error" in views directory

I am currently working on an angular website running express on a nodejs server. It usually loads up perfectly when I start running it on localhost but just yesterday it suddenly started throwing this error.
GET / 500 3.467 ms - 1595
Error: Failed to lookup view "error" in views directory "C:\node\nodetest1\routes\views"
at EventEmitter.render (C:\node\nodetest1\node_modules\express\lib\application.js:579:17)
at ServerResponse.render (C:\node\nodetest1\node_modules\express\lib\response.js:960:7)
at C:\node\nodetest1\server.js:63:7
at Layer.handle_error (C:\node\nodetest1\node_modules\express\lib\router\layer.js:71:5)
at trim_prefix (C:\node\nodetest1\node_modules\express\lib\router\index.js:310:13)
at C:\node\nodetest1\node_modules\express\lib\router\index.js:280:7
at Function.process_params (C:\node\nodetest1\node_modules\express\lib\router\index.js:330:12)
at next (C:\node\nodetest1\node_modules\express\lib\router\index.js:271:10)
at Layer.handle_error (C:\node\nodetest1\node_modules\express\lib\router\layer.js:67:12)
at trim_prefix (C:\node\nodetest1\node_modules\express\lib\router\index.js:310:13)
at C:\node\nodetest1\node_modules\express\lib\router\index.js:280:7
at Function.process_params (C:\node\nodetest1\node_modules\express\lib\router\index.js:330:12)
at Immediate.next (C:\node\nodetest1\node_modules\express\lib\router\index.js:271:10)
at Immediate.<anonymous> (C:\node\nodetest1\node_modules\express\lib\router\index.js:618:15)
at runCallback (timers.js:674:20)
at tryOnImmediate (timers.js:645:5)
Here is my site directory tree:
nodetest1
bin
routes
libs
partials
views
server.js
package.json
I've been stuck on this for a day now and would really appreciate some help. Thanks!
Edit: Heres my server code below.
var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var mongoose = require('mongoose');
//This connects the Mongo DB
//var mongo = require('mongodb');
//var monk = require('monk');
//var db = monk('localhost:27017/appointment');
mongoose.connect('mongodb://localhost:27017/appointment');
var app = express();
var index = require('./routes/index');
var users = require('./routes/users');
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.engine('ejs', require('ejs').renderFile);
app.set('view engine', 'ejs');
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'routes')));
//Actually uses the mongodb
//app.use(function(req,res,next){
//req.db = db;
//next();
//});
app.use('/', index);
app.use('/users', users);
app.use('/api', require('./routes/api/appointment/'));
// catch 404 and forward to error handler
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
// error handler
app.use(function(err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
// render the error page
res.status(err.status || 500);
res.render('error');
});
module.exports = app;
The problem:
res.render('error');
You don't have file error.ejs in views directory
In your directory structure,
views is placed inside of routes directory.
Either you have to place it outside of routes directory or
define views path like this.
app.set('views', path.join(__dirname, 'routes/views'));

Catch all routes loading blank page Angular NodeJs

I was working on Angular app with routing (NodeJs as backend). Routing through pages works fine but when I try to reload page it gives 'cannot load path /home'. I browsed through and got to few solutions like THIS.
My code is
app.get('*', function (req, res) {
res.sendFile('mypath/index.html');
});
But this loads up blank page. Is there any way I can solve this issue?
This us how my server.js looks like
var express = require('express');
var app = express();
var bodyParser = require('body-parser');
var methodOverride = require('method-override');
var port = process.env.PORT || 8080; // set our port
var staticdir = process.env.NODE_ENV === 'production' ? 'dist.prod' : 'dist.dev'; // get static files dir
// get all data/stuff of the body (POST) parameters
app.use(bodyParser.json()); // parse application/json
//app.use(bodyParser.json({ type: 'application/vnd.api+json' })); // parse application/vnd.api+json as json
//app.use(bodyParser.urlencoded({ extended: true })); // parse application/x-www-form-urlencoded
app.use(methodOverride('X-HTTP-Method-Override')); // override with the X-HTTP-Method-Override header in the request. simulate DELETE/PUT
app.use(express.static(__dirname + '/' + staticdir)); // set the static files location /public/img will be /img for users
// routes ==================================================
app.set('views', __dirname + '/app');
app.set('view engine', 'html');
require('./devServer/routes')(app); // configure our routes
// start app ===============================================
app.listen(port); // startup our app at http://localhost:8080
console.log('Starting sever on port ' + port); // shoutout to the user
exports = module.exports = app; // expose app
app.get('/', function (req, res) {
res.render('index', {
page: 'index'
}
});
then out this into your config,
app.set('views', 'directory where index.html is');

static resource not loaded in node app.js file

My app.js is as below
var express = require('express');
var path = require('path');
var bodyParser = require('body-parser');
var mongoose = require('mongoose'); //add for Mongo support
mongoose.connect('mongodb://localhost/flapperNews'); //connect to Mongo
var index = require('./routes/index');
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(express.static(path.join(__dirname, 'public')));
//rout to views
app.use('/', index);
app.get('/', function (req, res) {
res.send('Application Started');
console.log("Application Started.")
});
app.listen(3000);
module.exports = app;
My Directories are as follows
root -> node_modules -> all resource
root -> public -> javascripts -> angularApp.js
I got the following error
I think, your file angularApp.js is available in this url http://localhost:3000/javascripts/angularApp.js
nodejs normally blocks everything outside the public folder (in root) for the client to see
app.use(express.static(path.join(__dirname, 'public')));
this maps the public folder to: /public
so the client isn't able to access any other directory on your system
you need to change the app.use or the folder ;)

Prerender not serving up products

I am serving up angular pages from express. I cannot get prerender to serve up rendered pages for the products:
http://www.minilolo.com/?_escaped_fragment_=/products/Lolo-Pink
But other pages like this one are OK:
http://www.minilolo.com/?_escaped_fragment_=/products
I think I may need to add some express routes, but would like to know if I am on the right track. Thanks!
var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var app = express();
// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.set('view engine', 'ejs');
app.use(require('prerender-node').set('prerenderToken', 'xyz123'));
/**
* Development Settings
*/
if (app.get('env') === 'development') {
// This will change in production since we'll be using the dist folder
app.use(express.static(path.join(__dirname, '../client')));
// This covers serving up the index page
app.use(express.static(path.join(__dirname, '../client/.tmp')));
app.use(express.static(path.join(__dirname, '../client/app')));
// Error Handling
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: err
});
});
}
/**
* Production Settings
*/
if (app.get('env') === 'production') {
// changes it to use the optimized version for production
app.use(express.static(path.join(__dirname, 'dist')));
// added to serve up products pages
app.use(function(req, res) {
// Use res.sendfile, as it streams instead of reading the file into memory.
res.sendfile(__dirname + '/dist/index.html');
});
// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: {}
});
});
}
module.exports = app;
EDIT: I have tracked down the issue to prerender converting '?_escaped_fragment_=' into '#!'. Angular then doesn't know which route to use unless I have $locationProvider.hashPrefix('!') in place (which I don't want to use). I dont want the # prefix if it can be helped.
2015-09-07T12:17:17.566Z got 200 in 12713ms for http://localhost:3000/#!/products
2015-09-07T12:17:18.773Z Timed out. Sending request with HTML on the page
2015-09-07T12:17:18.785Z got 200 in 12732ms for http://localhost:3000/#!/products
2015-09-07T12:19:04.589Z getting http://localhost:3000/#!/products
As explained on the following links:
https://github.com/prerender/prerender/issues/198
https://developers.google.com/webmasters/ajax-crawling/docs/specification?hl=en
The query from the search has '?_escaped_fragment_=' at the end of the path, rather than straight after the fqdn.
http://www.minilolo.com/?_escaped_fragment_=/products/Lolo-Pink <-- not this
http://www.minilolo.com/products/Lolo-Pink?_escaped_fragment_= <-- this!

Resources