Node js how to handle file response - javascript

Hi i am trying to do ajax image upload.this is the work i got so far.
my index.html:
//index.html
<!DOCTYPE HTML>
<html lang="en-US">
<head>
<meta charset="UTF-8">
<title>File Upload showing Upload Progress</title>
<style>
* {
font-family: Verdana;
font-size: 12px;
}
</style>
</head>
<body>
<form action="/upload" method="post" enctype="multipart/form-data" id="MyUploadForm">
<input name="ImageFile" id="imageInput" type="file" />
<input type="submit" id="submit-btn" value="Upload" />
<img src="images/ajax-loader.gif" id="loading-img" style="display:none;" alt="Please Wait"/>
</form>
<div id="output"></div>
<script type='text/javascript' src='http://code.jquery.com/jquery-1.7.1.min.js'></script>
<script type='text/javascript' src='main.js'></script>
</body>
<script type="text/javascript" src="js/jquery.form.min.js"></script>
<script type="text/javascript">
$(document).ready(function() {
var options = {
target: '#output', // target element(s) to be updated with server response
beforeSubmit: beforeSubmit, // pre-submit callback
resetForm: true // reset the form after successful submit
};
$('#MyUploadForm').submit(function() {
$(this).ajaxSubmit(options); //Ajax Submit form
// return false to prevent standard browser submit and page navigation
return false;
});
});
//function to check file size before uploading.
function beforeSubmit(){
alert('ok');
//check whether browser fully supports all File API
if (window.File && window.FileReader && window.FileList && window.Blob)
{
if( !$('#imageInput').val()) //check empty input filed
{
$("#output").html("Are you kidding me?");
return false
}
var fsize = $('#imageInput')[0].files[0].size; //get file size
var ftype = $('#imageInput')[0].files[0].type; // get file type
//allow only valid image file types
switch(ftype)
{
case 'image/png': case 'image/gif': case 'image/jpeg': case 'image/pjpeg':
break;
default:
$("#output").html("<b>"+ftype+"</b> Unsupported file type!");
return false
}
//Allowed file size is less than 1 MB (1048576)
if(fsize>1048576)
{
$("#output").html("<b>"+fsize +"</b> Too big Image file! <br />Please reduce the size of your photo using an image editor.");
return false
}
$('#submit-btn').hide(); //hide submit button
$('#loading-img').show(); //hide submit button
$("#output").html("");
}
else
{
//Output error to older unsupported browsers that doesn't support HTML5 File API
$("#output").html("Please upgrade your browser, because your current browser lacks some new features we need!");
return false;
}
}
</script>
</html>
and my app.js
var express = require('express'); //Express Web Server
var bodyParser = require('body-parser'); //connects bodyParsing middleware
var formidable = require('formidable');
var path = require('path'); //used for file path
var fs =require('fs-extra'); //File System-needed for renaming file etc
var app = express();
app.use(express.static(path.join(__dirname, 'public')));
app.set('views', __dirname + '/views');
app.engine('html', require('ejs').renderFile);
/* ==========================================================
bodyParser() required to allow Express to see the uploaded files
============================================================ */
app.use(bodyParser({defer: true}));
app.route('/').get(function(req,res)
{
console.log("Server started!");
res.render('index.html');
res.end('done');
});
app.post('/upload', function(req, res) {
var form = new formidable.IncomingForm();
form.parse(req, function(err, fields, files) {
console.log(files);
res.send('fileinfo: ' +files);
});
});
var server = app.listen(3030, function() {
console.log('Listening on port %d', server.address().port);
});
I am getting the follwing response on server-side:
{ ImageFile:
{ domain: null,
_events: {},
_maxListeners: undefined,
size: 238027,
path: '/tmp/a7b06a71ff10de78cc8b941b18762b73',
name: 'bg.jpg',
type: 'image/jpeg',
hash: null,
lastModifiedDate: Sun Jun 01 2014 04:05:57 GMT+0530 (IST),
_writeStream:
{ _writableState: [Object],
writable: true,
domain: null,
_events: {},
_maxListeners: undefined,
path: '/tmp/a7b06a71ff10de78cc8b941b18762b73',
fd: null,
flags: 'w',
mode: 438,
start: undefined,
pos: undefined,
bytesWritten: 238027,
closed: true } } }
Now i want to know.How to move this file into upload folder. And also when i submit it goes in another page.I want to perform it without reloading is there any way for it in node? Thanks in advance.

fs-extra module has move method. Use it like this:
app.post('/upload', function(req, res) {
var form = new formidable.IncomingForm();
form.parse(req, function(err, fields, files) {
fs.move(files.ImageFile.path, __dirname + '/upload/' + files.ImageFile.name, function(err) {
if (err) return console.log(err);
console.log('Moved successfully');
});
res.send('fileinfo: ' + files);
});
});
So the uploaded file appears in upload folder with the original name. There are 2 caveats:
upload folder should exist;
if file with such name exists already it will not be overwritten, so maybe you should generate a unique filename on each upload (replace files.ImageFile.name with your unique filename).

Related

accessing variable of node into html file

I have an index.html file and an app.js nodejs file. I have a var in app.js which is the name and want to print that variable in my index.html page
Code
var name = "Utsav";
var HTTP = require('HTTP');
var fs = require('fs');
function onRequest(req, res){
fs.readFile('index.html', function(err, data) {
res.writeHead(200, {'Content-Type': 'text/html'});
res.write(data);
res.end();
});
}
<html lang="en">
<head>
<title>Enter your request</title>
</head>
<body>
<label for="Name:">Name</label><br>
<input type="text" id="req"><br>
</body>
I want the value of name from app.js to print in a text box in index.html
For displaying data in your index.html, you can pass it like this.
app.get('/profile', function(request, response) {
response.render('pages/profile', {
user : request.user
});
})
and then in the html, you can view it like this.
<div>
<form>
<fieldset>
<input type = "text" value = "<%= user.user.username %>" />
</fieldset>
</form>
</div>
Hope it helps :)

Module unrecognised in Angular while using Node & Mongo

Working on a primitive enough MEAN-stack project.
When I run the application, the data-binding fails as the module which makes the association between my View and Backend(makes the http connection to my DB) never gets instantiated, and goes unrecognised.
Following error message appears in the console
[$injector:modulerr] Failed to instantiate module moviesApp due to:
Error: [$injector:nomod] Module 'moviesApp' is not available! You either misspelled the module name or forgot to load it. If registering a module ensure that you specify the dependencies as the second argument.
Error message is fairly understandable. I seem to have incorrectly(or not at all) created the link between the view "MoviesList.html" and the file containing the module I mentioned above (moviesApp), in the file "Movies.js".
Movies.js makes use of a factory. I've checked the general syntax(can't see how incorrect code inside the actual factory would cause the module to go unrecognised). Having written a basic factory before on jsfiddle, i'm confident that the syntax should be fine. https://jsfiddle.net/Sheepy99/4wmd3zd0/ (granted I chained the factory in that example, but it's the same general premise)
Before I post the rest of my code, it's based off of the example contained here: http://www.dotnetcurry.com/nodejs/1032/nodejs-apps-in-visual-studio-mean-stack
Some of my code is different due to differing versions, and some bits being deprecated since the author published the article(also wondering why he consistently uses double double-quotes).
Any ambiguity or loose ends, ask away.
MoviesList.html
<html>
<!--<meta charset="UTF-8">-->
<title>Node-Express Movie List</title>
<link rel="stylesheet" href="http://netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css">
<!--<link rel="stylesheet" href="/styles/site.css">-->
 
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.16/angular.js"></script>
<!--<script src="/scripts/controller.js"></script>
<script src="/scripts/movies.js"></script>-->
<script src="../public/scripts/movies.js"></script>
<script src="../public/scripts/controller.js"></script>
</head>
<body>
<div class="container">
     <!--<div class="text-center" ng-app="moviesApp" ng-controller="MoviesCtrl">-->
<div class="text-center" ng-app="moviesApp" ng-controller="MoviesCtrl">
         <h1>Node-Express Movie List</h1>
         <div class="col-md-12" control-group="">
             <input type="text" style="width: 200px;" ng-model="newMovieText">
             <button id="btnAddTodo" class="btn" style="margin: 2px;" ng-click="addMovie()" ng-disabled="newMovieText">Add Movie</button>
         </div>
 
         <div class="col-md-5" sticky-note="">
             <h3 class="text-center">Released Movies</h3>
             <!--<div class="col-md-5" rowmargin="" todoitem="" ng-repeat="movie" in="" movies="" |="" filter:{released:true}"="">-->
<div class="col-md-5" rowmargin="" todoitem="" ng-repeat="movie" in="" movies="" filter:{released:true}>
                 <div class="thumbnail">
                     <input type="checkbox" ng-model="movie.watched" ng-change="movieWatched(movie)">
                      
                     <span ng-class="{watchedMovie: movie.watched}">{{movie.name}}</span>
                 </div>
             </div>
         </div>
 
         <div class="col-md-5" sticky-note="">
             <h3 class="text-center">Coming Up...</h3>
             <div class="col-md-5" rowmargin="" todoitem="" ng-repeat="movie" in="" movies="" filter:{released:false}>
                 <div class="thumbnail">
                     {{movie.name}}
                     <br>
                     <br>
                     <input type="button" value="Released!" class="btn btn-success" btn-link="" released-button="" ng-click="movieReleased(movie)" style="">
                 </div>
             </div>
         </div>
     </div>
</div>
</body>
</html>
movies.js
var app = angular.module('moviesApp', []);
 
app.factory('moviesCRUD', function ($http, $q) {
    function getAllMovies() {
        var deferred = $q.defer();
 
        $http.get('/api/movies').then(function (result) {
            deferred.resolve(result.data);
        }, function (error) {
            deferred.reject(error);
        });
 
        return deferred.promise;
    }
 
    function addMovie(newMovie) {
        var deferred = $q.defer();
 
        $http.post('/api/movies', newMovie).then(function (result) {
            deferred.resolve(result.data.movie);
        }, function (error) {
            deferred.reject(error);
        });
 
        return deferred.promise;
    }
 
    function modifyMovie(updatedMovie) {
        var deferred = $q.defer();
 
        $http.put('/api/movies/' + updatedMovie._id, updatedMovie).then(function (data) {
            deferred.resolve(data);
        }, function (error) {
            deferred.reject(error);
        });
 
        return deferred.promise;
    }
 
    return {
        getAllMovies: getAllMovies,
        addMovie: addMovie,
        modifyMovie: modifyMovie
    };
});
mongoOperations.js
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
//http://stackoverflow.com/questions/24908405/mongoose-and-new-schema-returns-referenceerror-schema-is-not-defined
//link recommends use of what's on line 2 as a solution
mongoose.Promise = global.Promise; //not using promises, this line removes a default setting and also gets rid of a warning about promises
mongoose.connect('mongodb://localhost/moviesDb');
var db = mongoose.connection;
//var movieSchema = mongoose.Schema({ *I shouldn't need this because i've declared "require('mongoose')"
var movieSchema = new Schema({
name: String, //doesn't like if I have spaces on each new line, before the use of characters
released: Boolean,
watched: Boolean
});
var MovieModel = mongoose.model('movie', movieSchema);
db.on('error', console.error.bind(console, "connection error"));
db.once('open', function () {
//console.log("moviesDb is open...");  
MovieModel.find().exec(function (error, results) {
if (results.length === 0) {
MovieModel.create({ name: "The Amazing Spider-Man 2", released: true, watched: false });
MovieModel.create({ name: "The Other Woman", released: true, watched: true });
MovieModel.create({ name: "Shaadi ke Side Effects", released: false, watched: false });
MovieModel.create({ name: "Walk of Shame", released: true, watched: false });
MovieModel.create({ name: "Lucky Kabootar", released: false, watched: false });
}
});
});
exports.fetch = function (request, response) {
MovieModel.find().exec(function (err, res) {
if (err) {
response.send(500, { error: err });
}
else {
response.send(res);
}
});
};
exports.add = function (request, response) {
var newMovie = { name: request.body.name, released: false, watched: false };
MovieModel.create(newMovie, function (addError, addedMovie) {
if (addError) {
response.send(500, { error: addError });
}
else {
response.send({ success: true, movie: addedMovie });
}
});
};
exports.modify = function (request, response) {
var movieId = request.params.movieId;
MovieModel.update({ _id: movieId }, { released: request.body.released, watched: request.body.watched }, { multi: false },
function (error, rowsAffected) {
if (error) {
response.send(500, { error: error });
}
else if (rowsAffected == 0) {
response.send(500, { error: "No rows affected" });
}
else {
response.send(200);
}
}
);
};
server.js
var http = require('http');
var express = require('express');
var bodyParser = require('body-parser');
var path = require("path");
 
var port = process.env.port || 1337;
 
var app = express();
//app.use(bodyParser()); //getting deprecated warning in shell when using this specific line
app.use(bodyParser.urlencoded({ extended: true }));
//app.use(bodyParser.json()); used in stackoverflow solution, can see potential benefit, but isn't helping
var mongoOps = require('./server/MongoOperations.js');
 
app.get('/', function (request, response) {
//response.sendfile("views/MoviesList.html");
//response.sendFile("views/MoviesList.html");
response.sendFile("views/MoviesList.html", { "root": __dirname });
});
app.get('/api/list', function (request, response) {
response.send([{ id: 1, name: "charlie" }, { "id": 2, "name": "ward" }]);
//'Hello World!');
});
app.get('/api/movies', mongoOps.fetch);
 
app.post('/api/movies', mongoOps.add);
 
app.put('/api/movies/:movieId', mongoOps.modify);
app.use(express.static(path.join(__dirname, 'public')));
app.listen(port);
controller.js
app.controller('MoviesCtrl', function ($scope, moviesCRUD) {
    $scope.released = { released: true };
    $scope.notReleased = { released: false };
     
    function init() {
        moviesCRUD.getAllMovies().then(function (movies) {
            $scope.movies = movies;
        }, function (error) {
            console.log(error);
        });       
    }
 
    $scope.movieReleased = function (movie) {
 
        moviesCRUD.modifyMovie({ _id: movie._id, name: movie.name, released: true, watched: movie.watched })
                  .then(function (result) {
                      if (result.status === 200) {
                          movie.released = true;
                      }
                  }, function (error) {
                      console.log(error);
                  });       
    };
 
    $scope.movieWatched = function (movie) {
        moviesCRUD.modifyMovie(movie)
                  .then(function (result) {
                      if (result.status === 200) {
                          console.log("Movie updated");
                      }
                  }, function (error) {
                      movie.watched = !movie.watched;
                  });       
    };
 
    $scope.addMovie = function () {
        moviesCRUD.addMovie({ name: $scope.newMovieText }).then(function (newMovie) {
            $scope.movies.push(newMovie);
            $scope.newMovieText = "";
        }, function (error) {
            console.log(error);
        });       
    };
 
    init();
});
Also, much of my html is being rendered as question marks inside diamonds. This has me absolutely puzzled. Just thought i'd put that out there.
As a noobie, any brief general suggestions would be welcomed, as in adjustments to my code for readability, or approach.
I made a few changes to your code to get Angular to "compile" it, but I didn't have the code for the controller so I could not finish setting it up. But if you look at this plunk, you can see my changes.
<html ng-app="moviesApp">
<head>
<!--<meta charset="UTF-8">-->
<title>Node-Express Movie List</title>
<script data-require="angular.js#1.6.1" data-semver="1.6.1" src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.1/angular.js"></script>
<link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" />
<!--<link rel="stylesheet" href="/styles/site.css">-->
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.16/angular.js"></script>
<!--<script src="/scripts/controller.js"></script>
<script src="/scripts/movies.js"></script>-->
<script src="movies.js"></script>
<!--<script src="../public/scripts/controller.js"></script>-->
</head>
You had issues with the placement of the HEAD in the HTML, plus you bootstrapped the application in the first DIV, which I guess it could work, but it is very non-standard. You start your application in a Plunk or Codepen to make it easier on yourself.
Have fun.
Figured it out:
Because I have the following line near the bottom of server.js, my directory automatically starts of public, when specifying directives for external modules(in this case controller.js and movies.js.
Therefore, my directives were incorrect.
As for the strange diamonds I had mentioned at the bottom of my question, it was due to my files being automatically being saved as ASCII when I created them, when they should've been UTF-8.
An annoying and pedantic problem, but i'm sure someone will eventually find some help from this.
app.use(express.static(path.join(__dirname, 'public')));

Not able to validate filters for Images in CollectionFS over meteor Platform

I am using CollectionFS package to upload Images over my meteor application but not able to validate file using filters, so far I can upload any file of any extension and of any size.
template
<template name="uploadPicture">
<label class="ui primary left labeled icon button" for="file" id="upload-div">
<i class="photo icon"></i>
Update Picture
<input type="file" id="file" class="myFileInput"/>
</label>
</template>
client/upload_picture.js
Template.uploadPicture.events({
'change .myFileInput': function (event) {
FS.Utility.eachFile(event, function(file) {
Images.insert(file, function (err, fileObj) {
// Inserted new doc with ID fileObj._id, and kicked off the data upload using HTTP
});
});
}
});
lib/collection/images.js is
Images = new FS.Collection("images", {
stores: [new FS.Store.FileSystem("images")],
filters: {
maxSize: 1048576, // in bytes
allow: {
contentTypes: ['image/*'],
extensions: ['png','jpg','jpeg','gif']
},
onInvalid: function (message) {
if (Meteor.isClient) {
alert(message);
} else {
console.log(message);
}
}
}
});
Images.allow({
'insert': function () {
// add custom authentication code here
return true;
}
});
need to replace the key filters with filter, after that it will start working as normal

Uploading image to Kinvey and Angularjs

I am trying to change what my app currently does so that instead of inputing a url to reference an image, it uploads the image to the Kinvey collection instead.
Here is a JSfiddle of how I am currently saving the info from my form to my kinvey collection.
http://jsfiddle.net/k6MQK/
Heres my angular code for saving the form data:
$scope.savePeep = function () {
var dataObj = angular.copy($scope.peep);
delete dataObj['$$hashKey'];
// Add the ad hoc fields to the peep object if they are filled out
if ($scope.adHocItem) {
dataObj.adHocLocation = $scope.adHocItem.normalized_location;
dataObj.adHocLocation_display = $scope.adHocItem.display_location;
}
KinveyService.savePeep(dataObj, function (_result) {
debugger;
// update local collection
KinveyService.setCollectionObject(_result.data, $stateParams.peepId);
$state.transitionTo('home');
});
};
I want to change it so that instead of a Text input like this:
<input type="text" id="menu_url" name="menu_url"
placeholder="" class="form-control" ng-model="peep.menu_url">
its a file upload input that works.
<input type="file" id="menu_url" name="menu_url"
placeholder="" class="form-control" ng-model="peep.menu_url">
Simple File Upload with Kinvey & AngularJS http://bit.ly/1ncdQLq
<!DOCTYPE html>
<html>
<head>
<title>Kinvey File Demo</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.9/angular.min.js"></script>
<script src="https://da189i1jfloii.cloudfront.net/js/kinvey-angular-1.1.4.min.js"></script>
</head>
<body ng-app="kinveyUploadApp" ng-controller="MainCtrl">
<input type="file" id="files" name="files[]" />
<p ng-if="fileModel">
File Size: {{fileModel.size}} Last Modified: {{fileModel['_kmd'].lmt | date:'yyyy-MM-dd HH:mm:ss Z'}}
</p>
<script>
angular.module('kinveyUploadApp', ['kinvey'])
.run(['$kinvey', function ($kinvey) {
// Kinvey initialization starts
var promise = $kinvey.init({
appKey: 'appKey',
appSecret: 'appSecret'
});
promise.then(function () {
// Kinvey initialization finished with success
console.log("Kinvey init with success");
}, function (errorCallback) {
// Kinvey initialization finished with error
console.log("Kinvey init with error: " + JSON.stringify(errorCallback));
});
}])
.controller('MainCtrl', ['$scope', '$kinvey', function ($scope, $kinvey) {
$scope.fileModel = {};
angular.element(document).find('input')[0].addEventListener('change', function (e) {
var theFile = e.target.files[0];
var promise = $kinvey.File.upload(theFile, {
_filename: theFile.name,
public: true,
size: theFile.size,
mimeType: theFile.type
}).then(function (_data) {
console.log("[$upload] success: " + JSON.stringify(_data, null, 2));
$scope.fileModel = _data;
}, function error(err) {
console.log('[$upload] received error: ' + JSON.stringify(err, null, 2));
});
}, false);
}]);
</script>
</body>

How do I upload a file using node js?

I have looked around and looked at various tutorials on how to upload a file using node/express. I feel like I am doing something wrong on either the HTML or JQuery side.
I am using the following link as a http://howtonode.org/really-simple-file-uploads.
However I am getting the error:
TypeError: Cannot read property 'fileUpload' of undefined at module.exports.fileCreate
Here is my code below:
uploadcontroller.js
fs.readFile(req.files.fileUpload.path, function (err, data) {
var newPath = __dirname + "/uploads/" + imgString;
fs.writeFile(newPath, data, function (err) {
});
});
html snippet
<div class="form-group">
<label for="fileUpload">Upload File</label>
<input type="file" name="fileUpload" id="fileUpload">
</div>
I am using the Sails framework (not sure if that makes difference)
Edit: Complete Form
<form role="form" class="uploadFileForm">
<div class="form-group">
<label for="fileTitleInput">Title</label>
<input type="text" name="formTitleInput" id="formTitleInput">
</div>
<div class="form-group">
<label for="fileDescriptionInput">Description</label>
<textarea class="form-control" rows="4" id="fileDescriptionInput"></textarea>
</div>
<div class="form-group">
<label for="fileUpload">Upload File</label>
<input type="file" name="fileUpload" id="fileUpload">
</div>
<button type="submit" class="btn btn-default" id="file-submit-btn">Publish to Web</button>
</form>
app.post('/upload', function(req, res) {
fs.readFile(req.files.image.path, function (err, data) {
var imageName = req.files.image.name
/// If there's an error
if(!imageName){
console.log("There was an error")
res.redirect("/");
res.end();
} else {
var newPath = __dirname + "/uploads/fullsize/" + imageName;
/// write file to uploads/fullsize folder
fs.writeFile(newPath, data, function (err) {
/// let's see it
res.redirect("/uploads/fullsize/" + imageName);
});
}
});
});
app.post('/', function(req, res) {
console.log(req.files);
fs.readFile(req.files.displayImage.path, function (err, data) {
var newPath = __dirname + "/uploads/"+req.files.displayImage.name;
fs.writeFile(newPath, data, function (err) {
if (err) throw err;
res.redirect("back");
});
});
});
Just for your reference, "console.log(req.files)" would contain something like this:
{ displayImage:
{ domain: null,
_events: null,
_maxListeners: 10,
size: 84654,
path: 'E:\\Users\\xyz\\AppData\\Local\\Temp\\90020831e2b84acb2d4851e4d4
2d77d5',
name: 'ccc - 1.jpg',
type: 'image/jpeg',
hash: false,
lastModifiedDate: Wed May 22 2013 07:47:39 GMT+0530 (India Standard Time),
_writeStream:
{ domain: null,
_events: null,
_maxListeners: 10,
path: 'E:\\Users\\xyz\\AppData\\Local\\Temp\\90020831e2b84acb2d4851e
4d42d77d5',
fd: 4,
writable: false,
flags: 'w',
encoding: 'binary',
mode: 438,
bytesWritten: 84654,
busy: false,
_queue: [],
_open: [Function],
drainable: true },
length: [Getter],
filename: [Getter],
mime: [Getter] }
}
I ran into the same problem. Sails did not recognize req.files (undefined). So your problem seems very much Sails related. The following solved my problem (especially the Skipper documentation).
In the 0.9 version of Sails, you can uncomment this line in the config/express.js file:
// bodyParser: require('express').bodyParser,
In the 0.10 version, use req.file instead of req.files.
See their beta documentation on file uploads: http://beta.sailsjs.org/#/documentation/reference/Upgrading
Be sure to check out the Skipper documentation as well: https://github.com/balderdashy/skipper. Most likely your version of Sails will use this to process the file uploads.

Categories