MongoDB / Express / Node File upload error
I'm working on a Mongo / Node / Express example to help me understand how full stack project chunks fit together. The app is pretty simple: the express server sends a page that the user can use to load the image. Photos are saved and users can use the site to view the uploaded images and view various features.
I haven't started implementing anything related to persistence or Mongo, so I'm pretty sure this is not a problem (which means it is possible). I am using these frameworks / packages:
Node.js: 0.10.33
- Express: 4.10.7
- Express-Handlebars: 1.1.0
- MongoDB: 1.4.28
- Mongoose: 3.8.21
Bauer: 1.3.12
- Bootstrap: 3.3.1
The error that I cannot identify appears when I try to upload an image file to the site. When I select an image file and hit submit, I get the following error in the browser ...
Connect 500 TypeError: Cannot read property 'file' of undefined at saveImage (/home/dan/development/tuts-book/controllers/image.js:47:37) at module.exports.create (/home/dan/development/tuts-book/controllers/image.js:66:9) at Layer.handle [as handle_request] (/home/dan/development/tuts-book/node_modules/express/lib/router/layer.js:82:5) at next (/home/dan/development/tuts-book/node_modules/express/lib/router/route.js:100:13) at Route.dispatch (/home/dan/development/tuts-book/node_modules/express/lib/router/route.js:81:3) at Layer.handle [as handle_request] (/home/dan/development/tuts-book/node_modules/express/lib/router/layer.js:82:5) at /home/dan/development/tuts-book/node_modules/express/lib/router/index.js:235:24 at Function.proto.process_params (/home/dan/development/tuts-book/node_modules/express/lib/router/index.js:313:12) at /home/dan/development/tuts-book/node_modules/express/lib/router/index.js:229:12 at Function.match_layer (/home/dan/development/tuts-book/node_modules/express/lib/router/index.js:296:3)
Here's the code I'm working with:
Package.json
{
"name": "tuts-book",
"version": "1.0.0",
"description": "Working example from Web Development with MongoDB and Node.js.",
"main": "server.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "Dan Schatz",
"license": "ISC",
"dependencies": {
"body-parser": "^1.10.1",
"cookie-parser": "^1.3.3",
"errorhandler": "^1.3.2",
"express": "^4.10.7",
"express-handlebars": "^1.1.0",
"method-override": "^2.3.1",
"moment": "^2.9.0",
"mongodb": "^1.4.28",
"mongoose": "^3.8.21",
"morgan": "^1.5.1"
}
}
Server: server.js
'use strict';
var express = require('express'),
config = require('./server/configure'),
app = express();
app.set('port', process.env.PORT || 3300);
app.set('views', __dirname + '/views');
app = config(app);
var server = app.listen(app.get('port'), function() {
console.log('Server up: http://localhost:' + app.get('port'));
});
Route file: routes.js
'use strict';
var home = require('../controllers/home'),
image = require('../controllers/image');
module.exports.initialize = function(app, router) {
router.get('/', home.index);
router.get('/images/:image_id', image.index);
router.post('/images', image.create);
router.post('/images/:image_id/like', image.like);
router.post('/images/image_id/comment', image.comment);
app.use('/', router);
};
View Wrapper: main.handlebars
<!DOCTYPE HTML>
<html lang="eng">
<head>
<meta charset="UTF-8">
<title>Tuts Book</title>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css" rel="stylesheet">
<link href="//maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet">
<link href="/public/css/styles.css" rel="stylesheet" type="text/css" >
</head>
<body>
<div class="page-header">
<div class="container">
<div class="col-md-6">
<h1><a href="/">imgPloadr.io</a></h1>
</div>
</div>
</div>
<div class="container">
<div class="row">
<div class="col-sm-8">
{{{body}}}
</div>
<div class="col-sm-4">
{{> stats this }}
{{> popular this }}
{{> comments this }}
</div>
</div>
</div>
<div style="border-top: solid 1px #eee; padding-top: 1em;">
<div class="container">
<div class="row">
<div class="col-sm-12 text-center">
<p class="text-muted">Schatz.com | © 2014</p>
<p class="text-center">
<i class="fa fa-twitter-square fa-2x text-primary"></i>
<i class="fa fa-facebook-square fa-2x text-primary"></i>
</p>
</div>
</div>
</div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script src="/public/js/scripts.js" type="text/javascript" ></script>
</body>
</html>
Index type: index.handlebars
<div class="panel panel-primary">
<div class="panel-heading">
<h2 class="panel-title">{{ image.title }}</h2>
</div>
<div class="panel-body">
<p>{{ image.description }}</p>
<div class="col-md-12 text-center">
<img src="/public/upload/{{ image.filename }}" class="img-thumbnail">
</div>
</div>
<div class="panel-footer">
<div class="row">
<div class="col-md-8">
<button class="btn btn-success" id="btn-like" data-id="{{ image.uniqueId }}"><i
class="fa fa-heart"> Like</i></button>
<strong class="likes-count">{{ image.likes }}</strong> - <i
class="fa fa-eye"></i> <strong>{{ image.views }}</strong>
- Posted: <em class="text-muted">{{ timeago image.timestamp }}</em>
</div>
</div>
</div>
</div>
<div class="panel panel-default">
<div class="panel-heading">
<div class="row">
<div class="col-md-8">
<strong class="panel-title">Comments</strong>
</div>
<div class="col-md-4 text-right">
<button class="btn btn-default btn-sm" id="btn-comment" data-id="{{ image
.uniqueId }}"><i class="fa fa-comments-o"> Post Comment...</i></button>
</div>
</div>
</div>
<div class="panel-body">
<blockquote id="post-comment">
<div class="row">
<form method="post" action="/images/{{ image.uniqueId }}/comment">
<div class="form-group col-sm-12">
<label class="col-sm-2 control-label" for="name">Name:</label>
<div class="col-sm-10">
<input class="form-control" type="text" name="name">
</div>
</div>
<div class="form-group col-sm-12">
<label class="col-sm-2 control-label" for="email">Email:</label>
<div class="col-sm-10">
<input class="form-control" type="text" name="email">
</div>
</div>
<div class="form-group col-sm-12">
<label class="col-sm-2 control-label" for="comment">Comment:</label>
<div class="col-sm-10">
<textarea class="form-control" name="comment" rows="2"></textarea>
</div>
</div>
<div class="form-group col-sm-12">
<div class="col-sm-12 text-right">
<button type="submit" id="comment-btn" class="btn btn-success"
type="button"><i class="fa fa-comment"></i> Post</button>
</div>
</div>
</form>
</div>
</blockquote>
<ul class="media-list">
{{#each comments}}
<li class="media">
<a class="pull-left" href="#">
<img class="media-object img-circle" src="http://www.gravatar.com/avatar/{{
gravatar }}?d=monsterid&s=45">
</a>
<div class="media-body">
{{ comment }}
<br/><strong class="media-heading">{{ name }}</strong> <small
class="text-muted">{{ timeago timestamp }}</small>
</div>
</li>
{{/each}}
</ul>
</div>
</div>
I spent a couple of days exploring many different possibilities (including the new Express 4.0 content), but I ran out of leaders.
I also found this post: req.files question , but I already have this solution in my HTML.
If you have any thoughts, I am very grateful for the help. And if there is any relevant code that I have not included, let me know and I will add it. Thanks again.
source to share
Express 4 incompatible multiplayer messages, you will need to use Multer or Busboy. Have a look at GridFS as you need to store the pic in the mongo database associated with the user and can retrieve it later.
I personally would just have another server to download the pic instead, so you just need to process the link as text using your node.js - mongodb installation. Take a look at this explaining it step by step: https://devcenter.heroku.com/articles/s3-upload-node
source to share