Issues in image upload using Express JS and Parse Cloud hosting - javascript

I am using Cloud Code and Express, hosted on Parse to upload an image.
Here is the error on Parse log:
I2015-01-03T13:35:55.199Z] TypeError: Cannot read property 'thumbnail' of undefined
at app.js:40:25
at callbacks (express_router.js:161:37)
at param (express_router.js:135:11)
at pass (express_router.js:142:5)
at Router._dispatch (express_router.js:170:5)
at Object.router (express_router.js:33:10)
at next (connect_proto.js:240:15)
at Object.expressInit [as handle] (express_middleware.js:31:5)
at next (connect_proto.js:240:15)
at Object.query [as handle] (connect_query.js:44:5)
It seems that Express JS/Parse is not able to understand req.files.XXX. There error is coming in app.js at following line: console.error(req.files.thumbnail.size);
Also, req.files print following error: No Message provided
Here is the recipecontent.ejs code:
<!DOCTYPE html>
<html>
<form method="post" enctype="multipart/form-data" action="/saverecipecontent">
Enter Recipe Image 1:
<input type="file" name="thumbnail" id="thumbnail">
<input type="submit">
</form>
</html>
Here is app.js code:
// These two lines are required to initialize Express in Cloud Code.
var express = require('express');
var app = express();
// Global app configuration section
app.set('views', 'cloud/views'); // Specify the folder to find templates
app.set('view engine', 'ejs'); // Set the template engine
app.use(express.bodyParser()); // Middleware for reading request body
app.get('/recipecontent', function(req, res) {
res.render('recipecontent', {
recipe_name: 'e.g. Rice Cake'
});
});
app.post('/saverecipecontent', function(req, res) {
console.error(req.files.thumbnail.size);
console.error(req.files.thumbnail.path);
console.error(req.files.thumbnail.name);
console.error(req.files.thumbnail.type);
Parse.Cloud.run('saveRecipeImage', req.body, {
success: function(result) {
// result is 'Hello world!'
},
error: function(error) {
}
});
});
// Attach the Express app to Cloud Code.
app.listen();
Finally here is the main.js code:
require('cloud/app.js');
Parse.Cloud.define("saveRecipeImage", function(request, response) {
var recipeContent = Parse.Object.extend("recipe_content");
var recipeContentObj = new recipeContent();
console.error(request.params);
var file = request.params.thumbnail;
var name = "photo.jpg";
var parseFile = new Parse.File(name, file);
parseFile.save().then(function(parseFile) {
// The file has been saved to Parse.
var url = parseFile.url();
recipeContentObj.set("recipe_imgurl1", url);
return recipeContentObj.save();
}, function(error) {
// The file either could not be read, or could not be saved to Parse.
});
});
Please help!

I raised this bug in Parse, here is the update:
The middleware we support for express.js does not support file uploads.
What you can do instead is sending the file contents as base64 to your endpoint and create the Parse.File object from this data.
Here is the updated code utilizing file contents as base64 to endpoint and creating Parse.File object:
Here is the layout.ejs code
< html >
< head >
< script src = "//ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js" > < /script>
<script src="/ / cdnjs.cloudflare.com / ajax / libs / underscore.js / 1.4.4 / underscore - min.js "></script>
<!-- <% if (locals.title) { %> -->
<!-- <title><%= title %></title>
<% } else { %>
<title>AnyImg</title>
<% } %> -->
<link href='//fonts.googleapis.com/css?family=Open+Sans' rel='stylesheet' type='text/css'>
<script src=" / javascripts / backbone.js "></script>
<script src="
https: //www.parsecdn.com/js/parse-1.2.8.min.js"></script>
< script >
Parse.initialize("n47hKoBkN2vbAAjIPd8rj6Dnc9P6zKYIlXvlZo3x", "a960Z8aOzTNOaKMUcvDQ7lvzT2v2VTHABh6lAdNx"); < /script>
<script type="text/javascript
" src=" / javascripts / main.js "></script>
</head>
<body>
<div id="
content ">
<div id="
bar ">
<h1>File Upload</h1>
</div>
<div id="
main ">
<form id="
upload ">
<div class="
outer ">
<div>
<input type="
text " name="
title " placeholder="
Untitled " />
<input id="
asd " type="
file " />
</div>
</div>
</form>
<img id="
img " src="
" />
<div id="
base "></div>
</div>
</div>
</body>
</html>
// These two lines are required to initialize Express in Cloud Code.
var express = require('express');
var app = express();
// Global app configuration section
app.set('views', 'cloud/views'); // Specify the folder to find templates
app.set('view engine', 'ejs'); // Set the template engine
app.use(express.json());
app.use(express.urlencoded());
app.get('/', function(req, res) {
res.render('layout', {
recipe_name: 'e.g. Rice Cake'
});
});
app.post('/newUploadImage', function(req, res) {
var file = new Parse.File("logo.png", {
base64: req.body.image
});
file.save().then(function() {
console.log("file saved");
console.log(file.url());
});
if (req.params.image) {
console.log("data found12345");
}
});
app.listen();
Here is the image js
var base64Data;
var imageName = '';
function readImage(input) {
if (input.files && input.files[0]) {
imageName = input.files[0].name;
var FR = new FileReader();
FR.onload = function(e) {
$('#img').attr("src", e.target.result);
$('#base').text(e.target.result);
base64Data = e.target.result;
var datObj = {
image: e.target.result,
name: imageName
};
var test = {
image: '12sds'
};
$.ajax({
type: "POST",
data: datObj,
url: '/newUploadImage',
dataType: "json",
success: function(msg) {
alert(msg.url);
console.log();
},
error: function(errormsg) {
console.log(errormsg);
alert("Sorry, there was an error uploading the image.");
}
});
};
FR.readAsDataURL(input.files[0]);
}
}
$(function() {
// Make all of special links magically post the form
// when it has a particular data-action associated
$("#asd").change(function() {
readImage(this);
alert('Test');
});
});
Thanks!

It looks like you're trying to use body-parser middleware to parse a multipar body but as stated on the github page of body-parser itself:
This does not handle multipart bodies, due to their complex and
typically large nature.
You need another parser to handle multipart bodies.
I suggest you multer but there are many others available.

Related

Error: friends.js:1 Uncaught SyntaxError: Unexpected token <, after using express.static and change html content after button click

I am trying to display home.html on initial load of localhost:9000, but when I do when the way my current code is, I get the error: friends.js:1 Uncaught SyntaxError: Unexpected token <. I am not sure what this error means. Also, when I do windows.location = localhost:9000/list, in my display.js, the get requests will not send the list.html to the browser, and nothing changes. I tried putting the get request in both server.js and display.js but they both do nothing.
Directory layout
dir main
-server.js
dir subMain
dir display
-display.js
dir routing
-routes.js
dir public
-home.html
-list.html
server.js
var path = require('path');
var express = require('express');
var app = express();
require('./subMain/routing/routes.js')(app, path, express);
app.listen(9000, function(){
console.log('connected on 9000')
})
//app.get('/list', function(request, response){
// response.sendFile(path.join(__dirname + '/..', 'public', 'list.html'));
//});
routes.js
module.exports = function(app, path, express){
app.use(express.static("subMain"))
app.use(express.static(__dirname + "/public"));
app.use(express.static(__dirname + "/routing"));
app.use(express.static(__dirname + "/display"));
app.use(function(request, response, next){
response.sendFile(path.join(__dirname + "/..", "public", "home.html"));
})
app.get('/list', function(request, response){
response.sendFile(path.join(__dirname + '/..', 'public', 'list.html'));
});
}
display.js
$(document).on('click', '#btn', sendSurvery);
function sendSurvery(){
window.location = 'survey.html';
//var myQueryUrl = "http://localhost:9000/survey";
//$.ajax({url: myQueryUrl, method: 'GET', success: function(result){
// location.href = "http://localhost:9000/list"
//}}).done(function(response){
//});
}
home.html
<!DOCTYPE html>
<html>
<head>
<title>Friend Finder Home Page</title>
</head>
<body>
<div class="rowOne">
<!-- <div class="jumbotron col-lg-6"> -->
<h1>Hello, world!</h1>
<p>Click the button</p>
<button id="btn" style="width: 200px;">BUTTON</button>
<!-- </div> -->
</div>
<script src="https://code.jquery.com/jquery.js"></script>
<script type="text/javascript" src="../data/friends.js"></script>
</body>
</html>
You haven't supplied your home.html file, but the issue you're encountering is that your friends.js is not being found by express, and your home.html file is being returned instead. The first character in your home.html file is < and this is why you're getting the error. Check you are referencing the correct path of friends.js and that it is present in your static assets folder.
To confirm my explanation, you can directly access the url you're using to access friends.js and see the contents of home.html returned.

Node.js server issue - added "/" when looking for files in browser

I'm trying to write my first Nodejs server for getting to know Angular/Node and eventually the whole MEAN stack.
My server is running but there's a problem in my code, for some reason when I enter a non existing file, it should redirect to 404, but it doesn't. For some reason the URL gets a double dash;
How would I go about making the redirect to 404 work?
check this image
Here is my code for the server so far.
var http = require('http'),
fs = require('fs'),
path = require('path'),
root = __dirname + '/public/', //magic var
mime = require('mime');
//Server
var server = http.createServer(function (req, res) {
// Check is root is queried
var fileName = '';
var url = req.url;
if (url === '/'){
url = 'index.html'; // redirect when no file specified
}
fileName = root + url;
// check if file exists
fs.exists(fileName, function(exists){
if (exists) {
serveFile(fileName); // yes
} else {
path = root + '404.html'; //no
serveFile(fileName);
}
})
//serve file
function serveFile(requestFile) {
// maak a stream based on events
var stream = fs.createReadStream(requestFile);
res.writeHead(200, {'Content-Type': mime.lookup(requestFile)});
stream.on('data', function (chunk){
res.write(chunk);
});
stream.on('end', function(){
res.end();
});
stream.on('error', function(err){
console.log('error: '+ err);
});
}
});
server.listen(3000); //server start
console.log('Server gestart op http://localhost:3000 ');
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>angular</title>
<link href="https://cdn.jsdelivr.net/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet"/>
<link href="styles/app.css" rel="stylesheet"/>
</head>
<body ng-app class="bg">
<h1>First name?</h1>
<input type="text" placeholder="Type your name" ng-model='firstName'
class="input-lg"/>
<p>
Hi, {{firstName}}
</p>
<img src="https://static.pexels.com/photos/7720/night-animal-dog-pet.jpg" height="100px" width="100px"/>
</body>
<script type="text/javascript" src="https://cdn.jsdelivr.net/angularjs/1.5.5/angular.min.js"></script>
<script type="text/javascript" src="https://cdn.jsdelivr.net/angularjs/1.5.5/angular.min.js"></script>
</html>
Could anyone tell me what's going wrong here?
Thanks in advance!
get rid of the '/' after public:
root = __dirname + '/public'
It is the default behaviour of Node JS. ie. If you request for xxx.com/sample.txt, then the req.url will be "/sample.txt".
https://nodejs.org/api/http.html#http_message_url
So you have consider that in your code, as #Jordan mentioned, remove the "/".
Your redirect also should work fine.

node js: unable to render json data in the html table(shows blank), but the url shows the data

I am new to node js.
I am writing a nodejs application to fetch data from mongoDB and display on the page in a table. But the data is not getting displayed.
Usecase is:
User will navigate to localhost:8999/ to go to the main page called Queue. Here a link for a page HealthReport is present, clicking on which user would navigate to healthreport.html where I need to display the data from mongo.
I am able to view the json data in the browser, but displaying it in the required page is not working.
Is there any particular directory structure I need to follow ?
I am using a js file to do that but its not working.
That file is healthreport-db.js below:
$(function() {
var startTime = new Date();
startTime.setMonth(startTime.getHours() - 6);
$.ajax({
url : "http://localhost:8999/healthreport/getHealthReport",
dataType: "json",
success : function(data) {
var latest = data.length - 1;
var snapShotTime = moment.utc(data[latest].snapShotTime).toDate();
var nfs = data[latest].nfs;
var hive = data[latest].hive;
console.log("db.js hit");
// Add values to Hive Stats Table
$("#nfs").text("NFS: "+nfs);
$("#hive").text("HIVE: "+hive);
},
error : function() {
console.log("failed to get hiveInfo data");
}
});
});
healthreport.html file (where i need to display the parsed json data) in "views" directory:
<html>
<head>
<title>HealthReport</title></head>
<body>
Health Report
<table>
<tr>
<th>value</th>
</tr>
<tr>
<td id="nfs"></td>
</tr>
<tr>
<td id="hive"></td>
</tr>
</table>
<script src="healthreport-db.js"></script>
</body>
</html>
queue.html file in "views" directory:
<html>
<head>
<title>Queue</title></head>
<body>
Queue<br>
Health Report
</body>
</html>
I have a main js file called main_web.js:
var mongoose = require('mongoose');
var express = require('express');
var bodyParser = require('body-parser');
var collectorConn = mongoose.createConnection('mongodb://localhost:27017/mongotest3');
exports.collectorConn = collectorConn;
var app = express();
var publicOpts = { maxAge: 86400000 }; // Max age of 1 day for static content
// Routes
var route = require('./route.js');
var healthReport = require('./healthReportRoute.js');
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: false}));
app.use(express.static('public', publicOpts)); //all client source will be in public folder
app.use(express.static('views')); //views folder contains html & ejs files
app.set('view engine', 'ejs');
app.engine('html', require('ejs').renderFile); //render html files as ejs
// Route handlers
app.use('/', route);
app.use('/healthreport', healthReport);
var port = process.env.PORT || 8999;
app.listen(port);
console.log("open your browser to localhost:" + port);
exports.app = app;
Then I have a route.js that is acting as the router:
var express =require('express');
var router = express.Router();
/* Home page */
router.get('/', function(req, res, next) {
res.render('./queue.html',{title: "Queue"});
});
router.get('/healthreport', function(req, res, next) {
res.render('./healthreport.html',{title: "HealthReport"});
});
module.exports = router;
And then I have a healthReportRoute.js that is able to fetch the json data on the web using the url localhost:8999/healthreport/getHealthReport :
var express =require('express'); //add express
var router = express.Router();
var moment = require('moment'); //add moment
//mongoose schema
var appTableProdSchema = require("./appTableProdSchema.js");
router.get('/getHealthReport', function(req, res) {
// Return the most recent document
var records = appTableProdSchema
.find()
.sort({'_id': -1})
.limit(1)
.exec(function(err, data) {
if (err) return res.sendStatus(500);
res.json(data);
});
});
module.exports = router;
The appTableProdSchema.js is :
var conn = require('./main_web').collectorConn;
module.exports = conn.model('AppTableProd', {
snapShotTime : String,
nfs: Array,
hive: Array
});
I dont know how to get the data into the healthreport.html page.
Please help
You are making heavy use of the jQuery library but have not imported it.
Every time you have $ in your healthreport-db.js, you are attempting to reference the jQuery library.
You can download the library and include it in your project or you can link directly to the library hosted at one of many cdn's. Here's the documentation and the code to import from google's cdn:
http://jquery.com/download/
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.2/jquery.min.js"></script>
Your healthreporter.html would look like this:
<html>
<head>
<title>HealthReport</title></head>
<body>
Health Report
<table>
<tr>
<th>value</th>
</tr>
<tr>
<td id="nfs"></td>
</tr>
<tr>
<td id="hive"></td>
</tr>
</table>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.2/jquery.min.js"></script>
<script src="healthreport-db.js"></script>
</body>
</html>

Cannot post in node.js

I want to upload file using node.js , being new to it a tried to check if the file is being send to server.
html
<html>
<head>
<title>File Uploading Form</title>
</head>
<body>
<h3>File Upload:</h3>
Select a file to upload: <br />
<form action="img" method="POST"
enctype="multipart/form-data">
<input type="file" name="file" size="50" />
<br />
<input type="submit" value="Upload File" />
</form>
</body>
</html>
js
var express = require("express");
var app=express();
var http=require("http").Server(app);
app.get("/",function(req,res){
res.end("hello")
});
app.get("/upload",function(req,res){
res.sendFile(__dirname + "/form.html")
})
app.post("/img",function(req,res){
if(req.files){
console.log(req.files.file.name);
}
else{
console.log("ee")
}
});
http.listen(3000,function(){
console.log("listening on 3000")
})
When i upload something , it throws error
Cannot read files of undefined
Being new to back end i have no idea why its happening , why doesnt the server recieve the file?
You need to app.use() a fileparser. For example, you could use connect-busboy. You can get more information about options and usage at above link; a simple setup would be somehting like this:
var busboy = require('connect-busboy');
app.use(busboy());
app.post("/img",function(req,res){
req.busboy.on('file', function (fieldname, file, filename, encoding, mimetype) {
// ...
});
req.busboy.on('field', function (key, value, keyTruncated, valueTruncated) {
// ...
});
req.pipe(req.busboy);
// etc ...
});
As stated in the above answer, you must use a body parser for multipart bodies, but the better solution is to use the express middleware multer which lets you to use req.files just like in your OP.
Also, multer is built on top of busboy which is the fastest multipart body parser for node.js
With multer:
var express = require('express'),
multer = require("multer"),
app = express();
app.use(multer({
dest: path.resolve(__root + path.sep + config.get("localFolders").rawImages),
limits: {
files: 2
}
}));
// handle file upload
app.post("/img", function (req, res, next) {
var image = req.files.image;
// do something with image;
console.log(image.name);
});
Have a look on the documentation for multer within the link provided above. Good luck. :)

Node.js Express receiving postman as empty

I'm working on a simple website and I'm having a problem when sending a JSON to the API. The JSON will be received as EMPTY if is sent using the html/js, but when using postman everything works as expected.
The structure of files is simply the server running on node.js, an html page with his javascript to build the JSON and send it.
The html file code as it follows :
<!DOCTYPE html>
<html lang="en">
<head>
<body>
</head>
Receiver Address
<input type="text" placeholder="Write the target address..." id="target_address"></input><br>
Message
<input type="text" placeholder="Write the message in plain text..." id="message"></input><br>
<input type="submit" value="Send" id="accept"></input>
<br>
<div id="results"><div>
</body>
<script src="js/jquery.js"></script>
<script src="js/main.js"></script>
</html>
The javascript file is :
var URL_API = "http://localhost:3000/nr";
$("#accept").click(function(e) {
e.preventDefault();
var url = URL_API;
var object = new Object();
object.L = 1;
object.B = ($("#target_address").val());
object.message =($("#message").val());
object.po = "ProofofOrigin";
var data = JSON.stringify(object);
console.log(data);
$.ajax({
url : url,
type : 'POST',
crossDomain : true,
dataType : 'json',
contentType : 'application',
data : data,
dataType:'json',
}).done(function(data, status, jqxhr) {
window.alert("Information sent successfully");
console.log(data.B);
}).fail(function(data) {
window.alert("ERROR");
});
});
Then the part of node which is executing when receiving the given POST :
router.post('/', function(req, res, next) {
var updateStep = Number(req.body.L)+1;
var ProofofOrigin = req.body.message + "Message signed - POO";
var info_JSON = {
address: req.body.B,
step: updateStep,
message: req.body.message,
po: req.body.po,
};
JSON.stringify(info_JSON);
//res.send("Address : " + req.body.B + " \nStep : " + req.body.L + " \nMessage : " + req.body.C + " \nPOO : " + req.body.Po);
res.send(info_JSON);
//console.log(info_JSON);
});
For some reason the req.body (where the JSON should be saved) is completely empty on the body, but if I send it using Postman it will work.
I don't know what could be wrong.
Please verify this:
In javascript (client side):
contentType : 'application/json',
In nodejs (server side):
var express = require('express');
var bodyParser = require('body-parser');
var app = express();
app.use(bodyParser.json());
app.post('/api/doSomething', function(req, res) {
var mydata = req.body.mydata;
...
return res.json({result: result});
});
You need to include the body parser module to be able to parse JSON bodies.

Categories