how to access to filename in my requst block in multer - ajax

I Need Access to file name in my request body because i want store in my db but i dont know handle that , this is my code :
var storage = multer.diskStorage({
destination: function (req, file, callback) {
var name = 'public/images/' + Math.floor((Math.random() * 10675712320) + 1);
fs.mkdir(name, (err)=> {
if (err) {
console.log(err);
} else {
** Im want pass name variable**
callback(null, name);
}
});
},
filename: function (req, file, callback) {
callback(null, file.originalname);
}
});
var upload = multer({storage: storage}).single('userPhoto');
app.post('/api/photo', function (req, res) {
***upload(req, res, function (data) {
I need access to file name here because i want store in my db***
console.log(data);
res.end("File is uploaded");
});
});
Im try this way but not working :
fs.mkdir(name, (err)=> {
if (err) {
console.log(err);
} else {
callback(name, name);
}
});

you can access to path from req.file.path like this :
var upload = multer({storage: storage}).single('userPhoto');
app.post('/api/photo', function (req, res) {
upload(req, res, function (data) {
console.log(req.file.path);
res.end("File is uploaded");
});
});

Related

Sails.JS Socket in Overridden Actions of the Controller

I've overridden an action in the controller that was generated from a blueprint API in Sails.JS.
I used the create action. Now I can't get a Sails.JS socket event from that action anymore, however, other actions are working fine.
io.socket.on('posts', function gotHelloMessage(data) {
console.log('Post!', data);
});
io.socket.get('/posts', function gotResponse(body, response) {
console.log('Posts: ', body);
})
What's the way to implement so that the create action also generates the event with my newly implemented actions?
create: function(req, res) {
if (
!_.has(req.body, "title") ||
!_.has(req.body, "body") ||
!_.has(req.body, "category")
) {
return res.serverError("No field should be empty.");
}
var uploadPath = "../../assets/posts";
return req
.file("thumbnail")
.upload({ dirname: uploadPath }, async function(err, uploadedFiles) {
if (err) return res.serverError(err);
let post;
try {
post = await Posts.create({
title: req.body.title,
body: req.body.body,
category: req.body.category,
thumbnail:
uploadedFiles.length === 0
? ""
: uploadedFiles[0].fd.split("/").reverse()[0]
}).fetch();
return res.json({ result: post });
} catch (err) {
return res.json({ error: err });
}
});
}

uploading profile pic in hapijs 17.0

I am using hapijs version 17.0.1. I am trying to upload an image using ajax request on a hapijs route. Here is my AJAX code to upload profile pic:
var image_file_input = document.getElementById("user_profile_upload");
image_file_input.onchange = function () {
if(this.files != undefined)
{
if(this.files[0] != undefined)
{
var formData = tests.formdata ? new FormData() : null;
if (tests.formdata)
{
//alert(file)
formData.append('image_file', this.files[0]);
formData.append('userId', user_id);
formData.append('memberId', member_id);
}
$.ajax({
url: "/v1/User/uploadUserPic",
data: formData,
type: "POST",
dataType: "json",
contentType: false,
processData: false,
contentType: "multipart/form-data",
success: function(data){
console.log(data);
var errMsg = null;
var resData = null;
if(data.statusCode == 200)
{
resData = data.result;
}
else
{
alert(data.message)
}
},
error: function(error){
alert(error);
}
});
}
}
}
And here is my Hapijs route Code:
var uploadUserPic = {
method: 'POST',
path: '/v1/Module/uploadUserPic',
config: {
description: 'Update Image For User',
tags: ['api', 'User'],
auth: 'session',
payload: {
output: 'stream',
parse: true,
allow: 'multipart/form-data'
},
validate: {
payload: {
userId : Joi.string().regex(/^[a-f\d]{24}$/i).required(),
memberId: Joi.string().required(),
image_file: Joi.object().required(),
},
failAction: FailCallBack
}
},
handler: function (request, reply) {
var resultData = null;
var error = null;
return new Promise(function (resolve) {
var multiparty = require('multiparty');
var fs = require('fs');
var form = new multiparty.Form();
form.parse(request.payload, function (err, fields, files) {
if(err)
{
error = err;
resolve();
}
else
{
var mkdirp = require('mkdirp');
var img_dir = "./files/users/";
mkdirp(img_dir, function (err) {
if (err)
{
error = err;
console.error(err);
resolve();
}
else
{
var oldpath = files.image_file.path;
var newpath = "./files/users/"+requestPayload.userId+".png";
fs.rename(oldpath, newpath, function (err) {
if(err)
{
error = err;
}
resolve();
});
}
});
}
});
}).then(function (err, result) {
if(err) return sendError(err);
if(error) return sendError(error)
return {
"statusCode": 200,
"success": true
};
});
}
}
The above code gives me following error cannot read property 'content-length' of undefined on line form.parse(request.payload, function (err, fields, files) {});
Please let me know If I am doing something wrong. If I replace the url in ajax request with anohter url that I have written in php then it works perfectly. which means that something is wrong with my hapijs/nodejs code.
There's a good post on how to handle file uploads in Hapi.js (written in version 16) https://scotch.io/bar-talk/handling-file-uploads-with-hapi-js
Since you are using payload.parse = true, I am not seeing a particular reason why you have to use multiparty. I have the following working code that would save files (of any type) uploaded from client into uploads directory on the server (Please do not use directly on production as no sanitation is done)
{
path: '/upload',
method: 'POST',
config: {
payload: {
output: 'stream',
parse: true,
allow: 'multipart/form-data'
},
validate: {
payload: {
files: Joi.array().single()
}
}
},
handler: function(request) {
const p = request.payload, files = p.files
if(files) {
console.log(`${files.length} files`)
files.forEach(async file => {
const filename= file.hapi.filename
console.log(`Saving ${filename} to ./uploads`)
const out = fs.createWriteStream(`./uploads/${filename}`)
await file.pipe(out)
})
}
return {result: 'ok'}
}
}
You can use the following curl command to test
curl http://localhost:8080/upload -F 'files=#/path/to/a/note.txt' -F 'files=#/path/to/test.png' -vvv
There are a few issues with your code. First in your $.ajax call, you have specified contentType twice, although it's not a syntax error but it's careless to code like that. Second the function's signature inside your .then() block is incorrect. You are mixing the idea of Promise and callback. I don't think the following line will be triggered
if(err) return sendError(err);
One last trivial thing, you said you are using Hapi 17 but based on the handler function's signature
handler: function (request, reply) {
...
Seems you are not totally onboard with Hapi17 as the new signature is
handler: function (request, h) {
And it's not just the rename of reply to h.

readTextAsync WinJS cannot work

I need to read content from file. I have global variable fileDate and I want to put content to this variable, but when I call load method, the variable is undefined.
var filename = "dataFile.txt";
var fileDate;
WinJS.UI.Pages.define("index.html", {
ready: function (element, options) {
loadDate();
console.log("main" + fileDate);
this.fillYearSelect();
},
function loadDate() {
return localFolder.getFileAsync(filename).then(function (file) {
return Windows.Storage.FileIO.readTextAsync(file).then(function (fileContent) {
fileDate = fileContent;
console.log("fileContent " + fileContent);
},
function (error) {
console.log("Błąd odczytu");
});
},
function (error) {
console.log("Nie znaleziono pliku");
});
}
Sorry for my English :)
Don't forget that javascript is asynchronous, when you call console.log("main" + fileDate), the method loadDate() is not finished, and that is why your fileDate is not defined (yet).
You could use promises to achieve this.
Here is an example based on your code :
var filename = "dataFile.txt";
var fileDate;
var applicationData = Windows.Storage.ApplicationData.current;
var localFolder = applicationData.localFolder;
function loadDate() {
return new Promise(function (onComplete, onError) {
localFolder.getFileAsync(filename).then(function (file) {
Windows.Storage.FileIO.readTextAsync(file).then(function (fileContent) {
fileDate = fileContent;
console.log("fileContent " + fileContent);
onComplete(fileDate);
},
function (error) {
console.log("Error on readTextAsync");
onError(error);
});
},
function (error) {
console.log("Error on getFileAsync");
onError(error);
});
});
}
Now loadDate()returns a promise, you can now use .then() method to do things when loadDate() is finished.
loadDate().then(function (fileDate) {
console.log("Content : " + fileDate);
},
function (error) {
console.log(error);
});

Can not connect with API , so couldn't retrieve post from db?

I got problem while I move into https://github.com/DaftMonk/generator-angular-fullstack.
Before my project was working. Here is code for frontend and backend part related to comment.
I am getting all time error 404. I don't know why I cannot find following path.
POST http://localhost:9000/api/providers/554a1dba53d9ca8c2a2a31ff/posts/554b1726f1116e00256e3d82/comments 404 (Not Found)
I am struggling couple of days to discover which part of my code have problem but I couldn't realize that.
server side
in comment.controller
// Creates a new comment in the DB.
exports.create = function(req, res) {
console.log('i ma inside api');
Post.findById(req.originalUrl.split('/')[3], function (err, post) { //here can not find post at all.
if (err) {
return handleError(res, err);
}
if (!post) {
return res.status(404).send('Post not found');
}
Comment.create(req.body, function (err, comment) {
if (err) {
return handleError(res, err);
}
post.comments.push(comment.id);
post.save(function (err) {
if (err) return handleError(res, err);
return res.status(201).json(comment);
});
});
});
};
route.js
app.use('/api/providers/:providerId/posts/:postId/comments', require('./api/provider/post/comment'));
index.js
var controller = require('./comment.controller.js');
var router = express.Router();
router.get('/', controller.index);
router.get('/:id', controller.show);
router.post('/', controller.create);
router.put('/:id', controller.update);
router.patch('/:id', controller.update);
router.delete('/:id', controller.destroy);
router.put('/:id/upvote', controller.upvote);
in client side:
factory:
//create new comment for post
ob.createComment = function(providerId, postId,comment) {
console.log('i am inside factory');
return $http.post('/api/providers/'+ providerId + '/posts/' + postId + '/comments' ,comment, {
headers: {Authorization: 'Bearer '+Auth.getToken()}
}).success(function(data){
_.forEach(ob.provider.posts,function(value,index){
if(value._id === post._id){
ob.posts[index].comments.push(data);
}
})
ob.current.comments.push(data)
// ob.provider1._id.posts.push(data);
});
};
in my controller
$scope.addComment = function(){
// if(!$scope.title || $scope.title === '') { return; }
if(!$scope.body || $scope.body === '') { return; }
console.log('$stateParams',$stateParams);
providers.createComment($stateParams.providerId, $stateParams.postId,{
//title: $scope.title,
body: $scope.body
});
$scope.body = '';
$scope.title = '';
};
This is my model in whole the project.

AJAX POST request never completes. Data posts to server

I am sending a post request via AJAX. The data successfully posts but the AJAX call never completes. Backbone on the front; Node on the back. I am including the save function from my backbone view and the express route.
save: function(event) {
event.preventDefault();
console.log( 'You signed up for ' + this.model.get('name'));
var name = this.model.get('name');
var courseDay = this.model.get('courseDay');
var time = this.model.get('time');
var location = this.model.get('location');
jQuery.post("/test/signups", {
"name" : name,
"courseDay" : courseDay,
"time" : time,
"location" : location,
}, function (data, textStatus, jqXHR) {
console.log("Post response:");
console.dir(data);
console.log(textStatus);
console.dir(jqXHR);
});
}
Route:
app.post('/test/signups', isLoggedIn, function (req, res){
User.findOne({'_id': req.user.id }, function(err, user) {
if (err)
return done(err);
if (user) {
user.signup.name = req.body.name;
user.signup.courseDay = req.body.courseDay;
user.signup.time = req.body.time;
user.signup.location = req.body.location;
user.signup.modified = req.body.modified;
user.update({$push: { "signup" :
{ name: user.signup.name,
courseDay: user.signup.courseDay,
time: user.signup.time,
location: user.signup.location,
modified: user.signup.modified
}
}},{safe:true, upsert:true},function(err){
if(err){
console.log(err);
} else {
console.log("Successfully added" + user.signup);
}
});
}
});
});
Your server side code needs to send a response. Try something like below. Note I try to cover all cases of an error, user not found, and user found.
app.post('/test/signups', isLoggedIn, function (req, res){
User.findOne({'_id': req.user.id }, function(err, user) {
if (err) {
return res.status(500).send(err);
}
if (user) {
user.signup.name = req.body.name;
user.signup.courseDay = req.body.courseDay;
user.signup.time = req.body.time;
user.signup.location = req.body.location;
user.signup.modified = req.body.modified;
user.update({$push: { "signup" :
{ name: user.signup.name,
courseDay: user.signup.courseDay,
time: user.signup.time,
location: user.signup.location,
modified: user.signup.modified
}
}},{safe:true, upsert:true},function(err){
if(err){
return res.status(500).send(err);
}
console.log("Successfully added" + user.signup);
res.send(user);
});
} else {
res.status(404).send();
}
});
});

Resources