nodejs write simple image blob - Upload.dataUrltoBlob - angularjs

Simple question. How do I save a image blob in Nodejs from angular.
AngularSide:
$scope.upload = function (dataUrl, picFile) {
Upload.upload({
url: 'http://test.dev:3000/register/user/uploads',
data: {
file: Upload.dataUrltoBlob(dataUrl, picFile.name)
},
}).then(function (response) {
$timeout(function () {
$scope.result = response.data;
});
}, function (response) {
if (response.status > 0) $scope.errorMsg = response.status
+ ': ' + response.data;
}, function (evt) {
$scope.progress = parseInt(100.0 * evt.loaded / evt.total);
});
}
nodejs side: Do I need middleware here? if so which one should I use?
router.post('/user/uploads', multipartMiddleware, function(req, resp) {
var newPath = "/Users/testUser/test_hold_files/" + req.files.file.originalFilename;
fs.writeFile(newPath, req.files.file, function(err) {
if (err) {
console.log("Data Error ");
return console.error(err);
}
});
res.status(200).jsonp({status: "status: success "});
});
right now this just writes out the file with correct name but its empty.

You used to be able to access the uploaded file through req.files.imageName and then you would fs.readFile from tmp and write it permanently, which is no longer the case in express 4.0
In Express 4, req.files is no longer available on the req object by default. To access uploaded files on the req.files object, use multipart-handling middleware like busboy, multer, formidable, multiparty, connect-multiparty, or pez.
Soooooooo, you can feel free to use which ever one of those middlewares names above and then follow their API for dealing with uploaded files like images. Hope this helps, enjoy.

Ok,
After a long time of messing with this stuff. I found an answer. It does load the file in my folder.
I feel this is only partial since it does not resize the actual file smaller. It is what is selected with https://github.com/danialfarid/ng-file-upload. I used the
Upload.upload({
url: 'http://test.dev:3000/register/user/uploads',
data: {
file: Upload.dataUrltoBlob(dataUrl, picFile.name)
},
This did zoom into the file on selected image. It did not make the actual file size smaller. I am still looking into this issue.
var formidable = require('formidable'),
util = require('util'),
fs_extra = require('fs-extra');
This is my post to accept images.
router.post('/user/uploads', function (req, res){
var form = new formidable.IncomingForm();
form.parse(req, function(err, fields, files) {
res.writeHead(200, {'content-type': 'text/plain'});
res.write('received upload:\n\n');
res.end(util.inspect({fields: fields, files: files}));
});
form.on('end', function(fields, files) {
/* Temporary location of our uploaded file */
var temp_path = this.openedFiles[0].path;
/* The file name of the uploaded file */
var file_name = this.openedFiles[0].name;
/* Location where we want to copy the uploaded file */
var new_location = "/Users/testUser/test_hold_files/";
fs_extra.copy(temp_path, new_location + file_name, function(err) {
if (err) {
console.error(err);
} else {
console.log("success!")
}
});
});
});
I have also noticed that I can view the file in chrome but not load it into gimp. Gimp gives me a file error.
Small steps I guess.
Maybe Datsik can give us some insight on what is going on here.
https://stackoverflow.com/users/2128168/datsik
Phil

Related

Corrupt zip file downloaded in angular

Angular client code:
$http.post('/zip', {
id: _id
})
.success(function (data, status, headers, config) {
var blob = new Blob([data], {type: "application/zip"});
var contentDisp = headers('content-disposition');
if (contentDisp && /^attachment/i.test(contentDisp)) {
var fileName = contentDisp.toLowerCase()
.split('filename=')[1]
.split(';')[0]
.replace(/"/g, '');
//The below command works but generates a corrupt zip file.
FileSaver.saveAs(blob, fileName);
}
})
.error(function () {
console.log("Could not download");
});
NodeJS Server Code:
app.route('/zip/')
.post(function(req, res) {
var output = fs.createWriteStream(join(outdir, outzipfile));
//Using s3zip to archive.
s3Zip
.archive({ s3: s3Client, bucket: bucket}, folder, s3_files)
.pipe(output);
output.on('close', function() {
//This sends back a zip file.
res.download(outPutDirectory + outputBcemFile);
});
output.on('error', function(err) {
console.log(err);
return res.status(500).json({error: "Internal Server Error"});
});
});
Although FileSaver.saveAs works and downloads the zip file, it seems to be corrupted. Is the type "application/zip" correct? I have also tried "octet/stream" and it downloads a corrupt zip file too. Any help would be highly invaluable! Thanks.
This is a bug mentioned in Git in below link :
https://github.com/eligrey/FileSaver.js/issues/156
To solve you need to add : responseType: 'arraybuffer' to your $http Request headers and it will work.

Video capture to not show in my gallery on phone

I am using ng-cordova's plugin capture to capture (https://github.com/apache/cordova-plugin-media-capture) videos inside of the ionic framework from a mobile phone.
$scope.captureVideo = function() {
var options = { limit: 1, duration: 10 };
$cordovaCapture.captureVideo(options).then(function(videoData) {
var i, path, len;
for (i = 0, len = videoData.length; i < len; i += 1) {
path = videoData[i].fullPath;
console.log("Path of the video is = " + path.toString());
}
}, function(err) {
// An error occurred. Show a message to the user
});
}
The problem is every video capture I take saves to my phones gallery which I do not want. If I capture an image it does NOT save to my phone's gallery which is what I would like with video capture. Is there a way to stop videos from being saved?
I tried deleting the file but apparently the video file is not saved
in cordovafile directories.
function DeleteFile() {
var filename = "20161024_095758.mp4";
var relativeFilePath = "file:/storage/C8F0-1207/DCIM/Camera";
console.log('data directory: '+cordova.file.dataDirectory);
window.resolveLocalFileSystemURL(relativeFilePath, function(dir) {
dir.getFile(filename, {create:false}, function(fileEntry) {
fileEntry.remove(function(){
alert('file removed');
// The file has been removed succesfully
},function(error){
alert('error'+JSON.stringify(error));
// Error deleting the file
},function(){
alert('file doesnt exist');
// The file doesn't exist
});
});
});
The code above to delete file results in Error Code:6. No modification allowed
Well, apparently WE CANNOT DELETE AND WRITE FILES FROM MICRO SD-CARD SINCE VERSION 4.4. It is read only now.. And, when the user deletes the file from the gallery, it would not be available for the project. Here is what i came up with.
I copied the video file to cordova's external directory from where i could read the file when wanted and delete as per the need. Plugins required are cordova-file-plugin and cordova-plugin-file-transfer
.controller('yourCtrl', function($scope,$cordovaCapture,$sce,$cordovaFile, $cordovaFileTransfer, $timeout) {
$cordovaCapture.captureVideo(options).then(function(videoData) {
console.log(JSON.stringify(videoData[0]));
console.log(cordova.file.externalDataDirectory);
$cordovaFileTransfer.download(videoData[0].fullPath, cordova.file.externalDataDirectory + 'my-video.mp4', {}, true).then(
function(result)
{
console.log('success: '+ result);
},
function (error)
{
console.log('error: '+ JSON.stringify(error));
},function (progress) {
$timeout(function () {
$scope.downloadProgress = (progress.loaded / progress.total) * 100;
});
},false);
$scope.clipSrc = $sce.trustAsResourceUrl(videoData[0].fullPath);
//$scope.videoSrc = videoData[0].fullPath;
}, function(err) {
alert('Err: <br />'+ JSON.stringify(videoData));
});
//delete the file according to filename.
$scope.deleteVideo= function(){
$cordovaFile.removeFile(cordova.file.externalDataDirectory, "my-video.mp4")
.then(function (result) {
console.log('Success: deleting videoData file' + JSON.stringify(result));
}, function (err) {
console.log('Error: deleting videoData file' + JSON.stringify(err));
});
}
})

Angularjs - downloading a file in a specific location

here is the situation.
I have an angular app that need to be used via a machine on wich you can put an USB key.
Several exports are possible from the corresponding backend and thoses exports (pdf, csv or rtf) need to be downloaded directly on the key, without asking the user.
Furthermore I need to be able to detect if the key is not present and show an error.
I don't think that it is doable using only angular with chromium.
I was thinking of making a local nodejs server on each machine that could access the filesystem for that. It works when using postman with form-data, but I don't know how I can pass a file donwloaded in angular to the nodejs server as a formdata, I keep getting incorrect pdf files.
TLDR :
I need to be able to have a chain like this :
get file from backend in angular
post a request to local (nodejs) server with the downloaded file
receive the file in nodejs to save it on disk
I am open to other ideas if this one doesn't work, as long as I can download this file I am happy.
current nodejs code, that works when i post the file using postman :
router.post('/save', function(req, res, next) {
console.log('savexvbxc');
var fstream;
//test if USB key is available
fs.stat(basePath, function(err, stats) {
if (err) {
console.log('error, key not present');
res.send(412, 'FAILURE');
}
var filename = basePath + 'toti.pdf';
console.log('filename is ' + filename);
if (req.busboy) {
console.log('busboy loaded');
req.busboy.on('file', function(fieldName, fileStream, fileName, encoding, mimeType) {
console.log('Saving: ' + filename + ' ' + fileName);
fstream = fs.createWriteStream(filename);
fileStream.pipe(fstream);
fstream.on('close', function() {
console.log('successfully saved ' + filename);
res.status(200).send('SUCCESS');
});
fstream.on('error', function(error) {
console.log('failed saved ' + filename);
console.log(error);
res.send(500, 'FAILURE');
});
});
req.busboy.on('error', function(error) {
console.log('failed saved ' + filename);
console.log(error);
res.send(500, 'FAILURE');
});
return req.pipe(req.busboy);
} else {
console.log('error, busboy not loaded');
res.send(500, 'FAILURE');
}
});
});
current angular code that do not work:
var dlReq = {
method: 'GET',
url: '/fep/documents/TVFI_FEP_0015_SFS_Specifications_Fonctionnelles_Detaillees_V00.9.pdf',
headers: {
'Content-Type': 'application/pdf',
'Accept': 'http://localhost:4000/fep/documents/TVFI_FEP_0015_SFS_Specifications_Fonctionnelles_Detaillees_V00.9.pdf'
},
responseType: 'arraybuffer'
};
$http(dlReq).then(function(data, status, headers, config) {
console.log(resp);
var file = new Blob([(resp)], {type: 'application/pdf'});
var formdata = new FormData();
formdata.append('file', file);
var request = {
method: 'POST',
url: 'http://localhost:4080/save',
data: formdata,
headers: {
'Content-Type': undefined,
'Accept': '*/*'
}
};
// SEND THE FILES.
$http(request)
.success(function(d) {
console.log('ok', d);
})
.error(function() {
console.log('fail');
});
});
Thank you

Download only new files on an Ionic app?

I want to download a file from a server only if the file is new. For example, by checking the file modified date. I am using the below code to download the file, but I am stuck where I need to compare the files before downloading. Can anyone please give me a solution for this.
.factory('fileDownloadService',['$cordovaFileTransfer', function($cordovaFileTransfer){
return{
fileDownload:function(){
// File for download
var url = "http://www.xxxxx/file-to-download.json";
// Get file name only
var filename = url.split("/").pop();
// Save location
var targetPath = cordova.file.externalRootDirectory + filename;
$cordovaFileTransfer.download(url, targetPath, {}, true).then(function (result) {
console.log('Download Successful');
}, function (error) {
console.log('Download Error');
}, function (progress) {
// Progress handling
});
}
}}])
Appreciate your help. Thank you

Using Node Buffer or fileStream with formData file upload

Update: I have more or less solved the problem using multipart (app.use(multipart({uploadDir: __dirname + '/../uploads'}))from these instructions), but still don't know why my original code (below) fails.
There have been numerous variations on this question, and I have tried the ideas there without success. I'm using a file uploading directive (and have since tried another open source alternative) to send a binary file to a node server, that runs the following code (based on an SO answer I can't now refind):
exports.receive = function(req, res) {
var fitFileBuffer = new Buffer('');
// req.setEncoding("binary"); //doesn't help
req.on('data', function(chunk) {
fitFileBuffer = Buffer.concat([fitFileBuffer, chunk]);
});
req.on('end', function() {
fs.writeFileSync(
"today2.fit",
fitFileBuffer,
'binary');
res.send(200);
});
};
If I upload today.fit and compare to today2.fit, they have the same Kb of data, but are not identical, and subsequent code fails to process the file. Given that this happens with two pieces of third party code I suspect the problem lies with my code.
Here are the details from the client side of the POST being made
In the end, when I realised that I wanted to avoid saving to disk, I modified generalhenry's code with some stuff from busyboy's site and my own use of a Buffer:
exports.receive = function (req, res, next) {
var busboy = new Busboy({ headers: req.headers });
var fileBuffer = new Buffer('');
busboy.on('file', function(fieldname, file, filename, encoding, mimetype) {
file.on('data', function(data) {
console.log('File [' + fieldname + '] got ' + data.length + ' bytes');
fileBuffer = Buffer.concat([fileBuffer, data]);
});
file.on('end', function() {
console.log('File [' + fieldname + '] Finished');
genXmlFromString(fileBuffer.toString(), function(data) {
res.json(data);
});
});
});
busboy.on('finish', function() {
console.log("'finish'");
});
req.pipe(busboy);
};
UPDATE: the client post details helped. You're not posting a file stream (which would have worked) you're posting a form stream. The good news is there are good modules for handling form streams.
You'll need to pipe the request stream into a form handling stream (such as busboy) which will handle the ------WebKitFormBoundary. . . part and them give you the file(s) as stream(s)
https://github.com/mscdex/busboy
var Busboy = require('busboy');
exports.receive = function(req, res, next) {
var busboy = new Busboy({ headers: req.headers });
busboy.on('file', function(fieldname, file, filename, encoding, mimetype) {
var fileWriteStream = fs.createWriteStream('today2.fit');
file.pipe(fileWriteStream);
});
busbody.on('finish', function() {
res.send(201);
});
req.pipe(busboy);
};

Resources