Downloading a file from MongoDB to local filesystem - angularjs

I have asked various questions and got only limited answers and it has gotten me this far:
Mongoose code :
app.get('/Download/:file(*)', function (req, res) {
grid.mongo = mongoose.mongo;
var gfs = grid(conn.db);
var file = req.params.file
var fs_write_stream = fs.createWriteStream('Program.cs');
var readstream = gfs.createReadStream({ filename: file });
readstream.pipe(fs_write_stream);
res.download(__dirname+'/Program.cs', 'Solution.cs', function (err) {
if (err) throw err;
else console.log("check console");
});
})
Angular code:
$scope.Download = function () {
$http.get(url + "/Download/"+"Program.cs")
.success(function (res) {
console.log(res);
})}
When I open my console angular just returns a blank line, when i look into the network aspect the header sais this:
I want to be able to store this file to my local file system to a path that I want to be able to choose myself. PLEASE help me out, I'm desperate, I have looked EVERYwhere for a solution, thank you very much in advance!

Try this instead of your client side download attempt:
<a class="btn" href="/Download/Program.cs" download>

Related

nodejs write simple image blob - Upload.dataUrltoBlob

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

Cordova File Plugin Has Wrong Directory

So I am building a cordova/phonegap app in angularjs 1 and I'm trying to save and read from a file called calendar.txt in the app's private directory/sandbox and can't.
My console logs while debugging show that there are no errors and the file is being created if it doesn't exist, and is being read correctly. However that is not the case. When I build and run on my device, the data is not saved. Also no file is created in the location specified.
I console logged the path it was trying to use and this is it:
file:///data/data/com.adobe.phonegap.app/files/calendar.txt
Here is the code I am using to open the file:
$rootScope.openFile = function(){
var pathToFile = cordova.file.dataDirectory + "calendar.txt";
console.log('path = ' + pathToFile);
window.resolveLocalFileSystemURL(pathToFile,
function(fileEntry){
fileEntry.file(function (file) {
var reader = new FileReader();
reader.onloadend = function (e) {
$rootScope.calendar = JSON.parse(this.result);
console.log('file opened');
console.log(JSON.parse(this.result));
};
reader.readAsText(file);
}, function(error){});
}, function(error){
if(error.code == FileError.NOT_FOUND_ERR){
$rootScope.calendar = new Year();
console.log('no file found so it was created');
$rootScope.saveFile();
}
else{
console.log(error);
}
});
};
And here is the code for my save the file:
$rootScope.saveFile = function(){
var data = JSON.stringify($rootScope.calendar, null, '\t');
var fileName = "calendar.txt"
window.resolveLocalFileSystemURL(cordova.file.dataDirectory,
function(directoryEntry){
directoryEntry.getFile(fileName, { create: true },
function (fileEntry) {
fileEntry.createWriter(
function (fileWriter) {
var blob = new Blob([data], { type: 'text/plain' });
fileWriter.write(blob);
console.log('file saved');
},
function (error){});
},
function (error){}
);
},
function(error){
console.log("Saving Error: Error during finding directory", error.message);
}
);
};
I have used this tutorial to get this far: Cordova File Plugin Tutorial
What am I doing wrong?
I assume that you are facing this issue in Android as i too faced the same. As per my understanding and googling, in android (atleast in android 5) you cant write in application data directory unless the phone is rooted. So you may have to use externalRootDirectory instead.
eg: window.resolveLocalFileSystemURL(cordova.file.externalRootDirectory,successCallback, errorCallback);
Hope it helps.

Downloading a file from Mongoose in Angular

I've managed to upload a file and store it in my MongoDB, but now I want to be able to downlaod this file from the same mongoDB. In server-side I'm using the GridFS module in Mongoose to upload and download using the gfs-read/write-stream.
Downlaod code in Mongoose looks like :
app.post('/Download', function (req, res) {
grid.mongo = mongoose.mongo;
var gfs = grid(conn.db);
var readstream = gfs.createReadStream({
filename: 'Program.cs'
});
readstream.pipe(res);
})
In my angular i have this so far:
$scope.Download = function () {
$http.post(url + "/Download")
.success(function (res) {
console.log(res);
})
}
the console.log response is shown here
I want to save this content into a .cs file in my local file system, also want to be able to prompt the user for the download-path, How do I do this?
Try below code
app.post('/Download', function (req, res) {
var filenameId = "";// mention _id value of 'Program.cs'
var filename = 'Program.cs';
var _id = new ObjectID(filenameId );
var gfs = new Grid(conn.db, "yourfile_collection_name");// default value is fs
gfs.get(_id, function(err, data) {
if (err)
throw err;
res.setHeader('Content-Disposition','attachment; filename="' + filename + '"');
res.send(data);
});
};

Generate pdf using stream in Angular

I am trying to generate pdf and display inside any Div, I am getting binary data from server but when I try to convert that stream it says failed to load pdf.
I googled it and saw response of many people saying use responseType: 'arraybuffer' but I am getting object from server and extracting binary from it so I can't use it, though I tried with this approach as well but it didn't work.
Here is my controller code:
correspondenceService.getCorrespondenceDocument(id).$promise.then(function (data) {
var file = new Blob([(data[0].documentBytes)], { type: 'application/pdf' });
var fileURL = window.URL.createObjectURL(file);
vm.content = $sce.trustAsResourceUrl(fileURL);
window.open(fileURL);
}, function (reason) { });
}
This is Service:
getCorrespondenceDocument: function (correspondenceId) {
return $resource(correspondenceUrl + "getCorrespondenceDocuments").query({ correspondenceId: correspondenceId });
}
and this is my webApi:
[Route("getCorrespondenceDocuments")]
[HttpGet]
public async Task<IEnumerable<Document>> GetCorrespondenceDocumentsAsync(int correspondenceId)
{
var documents = await _correspondenceFacade.GetCorrespondenceDocumentDetailsAsync(correspondenceId);
return Mapper.Map<IEnumerable<Document>>(documents);
}
Trying to display like this on View:
Please let me know where I am doing mistake. Many thanks in advance.
Regards,
Vivek
Finally I managed to do it. Problem is I was passing 3 parameters in $http.get(), now I am passing 2 parameters only.
getCorrespondenceDocuments: function (correspondenceId) {
return $http.get(correspondenceUrl + 'getCorrespondenceDocuments' + '?correspondenceId=' + correspondenceId, { responseType: 'arraybuffer' }).then(function (response) {
return response;
});
}
Though I don't like to pass any parameter using this "?" and specifying id but I couldn't find any solution to this problem.
Many thanks guys for going through my post.
Regards,
Vivek

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