upload file nodejs and angular formidable - javascript

I use formidable to upload file with angular and nodejs. But I can't post anything to server. Here is code I tried:
server
var form = new formidable.IncomingForm();
form.uploadDir = path.join(__dirname, '../public/uploads');
form.on('file', function(field, file) {
fs.rename(file.path,path.join(form.uploadDir,file.name),function(err) {
if(err)
console.log(err);
console.log('Success')
});
});
// log any errors that occur
form.on('error', function(err) {
console.log('An error has occured: \n' + err);
});
// parse the incoming request containing the form data
form.parse(req, function(err, fields, files) {
});
})
Html
<form enctype="multipart/form-data" class="form-horizontal" role="form" id = "form_email" ng-submit="pushMessage()">
Angular
$scope.formMessage={};
$scope.pushMessage = function() {
$http.post('/customers/message',$scope.formMessage).then(function(response) {
console.log(response);
});
};

i did not use this before. but ng-fileupload can do the favour for you. its simple and convinient. Here is the github documentation for that. https://github.com/danialfarid/ng-file-upload. Hope it will help for you

Related

How do I overwrite a file with the fs module?

I'm making an electron app for windows. When I try to overwrite a txt file it just deletes everything. I want that but the content I am trying to put is not writing to the file.
Here is the code for when receive a prompt to save:
ipcRenderer.on('saveFile', function(){
console.log(fileData.path)
fs.writeFile(fileData.path, editor.innerText, 'utf8', (err) => {
if(err) throw err;
console.log('File Saved')
})
})
Here is the code when I send the file data (file path, text in file, etc.):
fileBtn.addEventListener('change', function(e){
if(fileBtn.files[0].type.substring(0, 4) == 'text'){
file.ext = fileBtn.files[0].name.substr(fileBtn.files[0].name.indexOf('.'))
console.log(fileBtn.files[0])
file.path = fileBtn.files[0].path
file.text = fs.readFileSync(file.path, 'utf8');
ipcRenderer.send('newFile', file)
}else{
console.error('Not a valid file type')
return;
}
})

How to detect when user has saved file to local disk in Angular/NodeJS?

I'm creating a temporary JSON file in my NodeJS backend which holds the information the user has filled in a form. At the end of the form when user clicks on the download button, I run some Python script in NodeJS to validate the data and then create a temporary file of this JSON data and return it to user as a HTTP GET response.
Right now I'm using a timer to delete this temporary file after 10 seconds, which is bad. I want to know how to detect when the user has fully downloaded the file to their local disk from the browser so I can delete this temporary file in backend.
The client Angular code:
$scope.downloadForm = function() {
var data = formDataFactory.getDataForSubmission();
var url = '/FormSubmission/DownloadData';
// Below POST call will invoke NodeJS to write the temporary file
$http.post(url, data)
.success(function(data, status) {
$scope.downloadPath = data.filePath;
$scope.downloadFile = data.fileName;
url = '/tmp/forms/' + $scope.downloadFile;
// If the temporary file writing is successful, then I get it with a GET method
$http.get(url)
.success(function(data, status) {
$log.debug("Successfully got download data");
$window.location = $scope.downloadPath;
})
.error(function(data, status) {
$log.error("The get data FAILED");
});
})
.error(function(data, status) {
$log.error("The post data FAILED");
});
}
$scope.download = function() {
$scope.downloadForm();
setTimeout(function() { //BAD idea
$scope.deleteForm($scope.downloadPath);
}, 10000);
}
The server NodeJS code:
// POST method for creating temporary JSON file
router.post('/FormSubmission/DownloadData', function(req, res) {
if (!req.body) return res.sendStatus(400); // Failed to get data, return error
var templateString = formTmpPath + 'form-XXXXXX.json';
var tmpName = tmp.tmpNameSync({template: templateString});
fs.writeFile(tmpName, JSON.stringify(req.body, null, 4), function(err) {
if (err) {
res.sendStatus(400);
} else {
res.json({ fileName: path.basename(tmpName), filePath: tmpName, out: ''});
}
});
});
// Get method for downloading the temporary form JSON file
router.get('/tmp/forms/:file', function(req, res) {
var file = req.params.file;
file = formTmpPath + file;
res.download(file, downloadFileName, function(err) {
if (err) debug("Failed to download file");
});
});
Update:
I'm trying to use a stream now to send the data back, but for some reason this get method is called twice!? Can't understand why!!
// Get method for downloading the temporary form JSON file
router.get('/tmp/forms/:file', function(req, res) {
var filename = "ipMetaData.json";
var file = req.params.file;
file = formTmpPath + file;
var mimetype = mime.lookup(file);
const stats = fs.statSync(file);
res.setHeader('Content-disposition', 'attachment; filename=' + filename);
res.setHeader('Content-type', mimetype);
res.setHeader('Content-Length', stats.size);
console.log("Will send the download response for file: ", file);
//var path = __dirname + "\\..\\tmp\\forms\\form-auSD9X.json";
console.log("Creating read stream for path: " + file);
var stream = fs.createReadStream(file);
// This will wait until we know the readable stream is actually valid before piping
stream.on('open', function () {
// This just pipes the read stream to the response object (which goes to the client)
stream.pipe(res);
});
// This catches any errors that happen while creating the readable stream (usually invalid names)
stream.on('error', function(err) {
console.log("Caught an error in stream"); console.log(err);
res.end(err);
});
stream.on('end', () => {
console.log("Finished streaming");
res.end();
//fs.unlink(file);
});
});
if I understand your problem correctly, you can do this in different ways, but easiest way is first, remove the timer to remove the file, and remove it after the download completes from the backend as follows
router.get('/tmp/forms/:file', function(req, res) {
var file = req.params.file;
file = formTmpPath + file;
res.download(file, downloadFileName, function(err) {
if (err) debug("Failed to download file");
else {
// delete the file
fs.unlink(file,function(err){
if(err) debug(err);
})
}
});
});
The problem was with doing a get call and then change location to the file path which has the same path. I changed my API path and used the stream .on('end', callback) to remove the file.
// If the temporary file writing is successful, then I get it with a GET method
$http.get(url) --> this URL should be different from $window.location
.success(function(data, status) {
$log.debug("Successfully got download data");
$window.location = $scope.downloadPath;
})
.err

How to upload file to web service via Node and save the response as a file

I have been searching and testing various modules/methods in Node.js with the goal of being able to upload a file to my vendors API and save the response data (which is a .png file sent as binary data) to an image file. Most of the examples demonstrate how to upload a file to a Web directory, but not a Web service. Formidable (https://github.com/felixge/node-formidable) is an example where it is easy to store in a Web directory, but I don't see how I can perform a simple post of form data to a Web service.
I have looked into using request (https://github.com/request/request) to post a file, but am confused as to what to put in their form example, specifically here:
// Pass a simple key-value pair
my_field: 'my_value',
My current attempt is using a mix of formidable and request, but it fails with the following error:
TypeError: Cannot read property 'hasOwnProperty' of null
My HTML form is as follows:
<form action="/upload4" method="post" enctype="multipart/form-data">
<input type="file" name="myfile" />
<input type="submit" value="Upload" />
</form>
Here is my Node/Formidable/Request Code:
app.post('/upload4', function (req, res) {
var form = new formidable.IncomingForm();
form.parse(req, function (err, fields, files) {
var options = {
contentType: files.myfile.type,
metadata: { fileName: files.myfile.name }
};
request.post({ url: 'http://myendpoint.net/uploadPDF', formData: form }, function optionalCallback(err, httpResponse, body) {
if (err) {
return console.error('upload failed:', err);
}
console.log('Upload successful! Server responded with:', body);
var options = { contentType: 'image/png' };
blobSvc.createBlockBlobFromText(containerName, 'Reponse.png', body, options, function (error, result, response) {
if (!error) {
// Response from POST was uploaded to Azure as a PNG file
res.send(result);
} else {
console.log(error);
}
});
});
console.log(req);
});
At this point, I would be happy with just being able to POST my file using Node with the end goal of being able to save the response (of a png file) to Azure.

"Error: socket hang up" while streaming using multiparty and request modules

Here is the code:
var app = require("express")();
var multiparty = require("multiparty");
var request = require("request");
var ims = require("imagemagick-stream");
var fs = require("fs");
var Busboy = require('busboy');
app.post('/submit', function(httpRequest, httpResponse, next){
var form = new multiparty.Form();
form.on("part", function(part){
if(part.filename)
{
var formData = {
thumbnail: {
value: part,
options: {
filename: part.filename,
contentType: part["content-type"]
}
}
};
request.post({url:'http://localhost:7070/store', formData: formData}, function (err, httpResponse, body) {
if(err) {
return console.error('upload failed:', err);
}
console.log('Upload successful! Server responded with:');
});
}
})
form.on("error", function(error){
console.log(error);
})
form.parse(httpRequest);
});
app.get('/', function(httpRequest, httpResponse, next){
httpResponse.send('<form action="http://localhost:9090/submit" method="post" enctype="multipart/form-data"><input type="file" name="file" /><input type="submit" value="xxx" /></form>');
});
app.listen(9090);
Here I am uploading the file submitted by user to another server without saving it on disk.
I get error upload failed: { [Error: socket hang up] code: 'ECONNRESET' }.
And on the server running on port 7070 I get error Error: stream ended unexpectedly
If I replace part in value:part with a filesystem readable stream then it works fine.
I think its missing content-length header. But when I add it I get a different error.
Thanks in advance.

ParseFile: cannot call then in save function

I try to save an image using ParseFile in js sdk and I retrieve this error:
TypeError: Cannot call method 'then' of undefined
at Object.Parse.File.save (/PATH_TO_PROJECT/node_modules/parse/build/parse-latest.js:4281:43)
at null.<anonymous> (/PATH_TO_PROJECT/node_modules/parse/build/parse-latest.js:5984:21)
here is my ejs code:
<form class="basic-grey" action="/confirm" method="post" enctype="multipart/form-data">
<input id="picture" name="picture" type="file" class="button"</input>
</form>
controller:
confirm: function (req, res) {
var file = new Parse.File(req.files.picture.name, req.files.picture);
file.save().then(function(file) {
console.log('FILE: '+ file);
}, function(error) {
console.log('ERROR: '+ error.message);
});
}),
req.files.picture is defined, I don't understand why save does not work.
Could you help me ?
To save uploaded file to a specific location use the following
var fs = require('fs');
fs.readFile(req.files.picture.path, function (err, data) {
fs.writeFile('pathYouWantToSaveFile', data, function(err, result){
// done
// delete the file from temp location
fs.unlink(req.files.picture.path);
});
});
NB: req.file.picture.path is the temporary location where the file is uploaded.
to make use Parse.File you can try the following (not tested though).
var fs = require('fs');
fs.readFile(req.files.picture.path, function (err, data) {
var file = new Parse.File('pathYouWantToSaveFile', data);
file.save().then(function(file) {
console.log('FILE: '+ file);
}, function(error) {
console.log('ERROR: '+ error.message);
});
});

Categories

Resources