I am new to mongodb.
I stored binary data with below code snippet:
var data = fs.readFileSync(path);
var image = new mongodb.Binary(data);
//open connection/collection
var record = {picname: id, content: image };
collection.save(record, {safe: true}, function(err,result){
if(err)
console.log(err.stack);
});//save
I can see the record size in db. there is binary data. record size also matched with file size. am happy.
Now, retrieved same binary data from mongo and trying to send it in response:
var record = {picname: id};
collection.findOne(record, function(err,result){
if(err)
console.log(err.stack);
else
{
console.log('before read from db for download.');
//HOW TO READ IMAGE/BINARY DATA FROM RESULT?
//I need to send result in response. Any Idea?
console.log('before read from db for download');
}
});
I am sending binary data with below code snippet. It's not working for all the files. What could be the issue:
collection.findOne(record, function(err,result){
if(err)
console.log(err.stack);
else
{
console.log('before read from db for download. result: [' + result.picname + " ], type: " + result.imagetype);
res.end(result.content.buffer, "binary");
console.log('Responded SUCCESS: ' + id );
}
});//findOne
Please let me know how to retrieve and send via response.
Thanks in advance
DD.
Your problem here is not so much with storing and reading the data, but is actually all about content types. So ideally you want to store this with your data as well as return the correct header information when you send the response.
So part of this would be mime type detection. There are modules available, mmmagic is one of them
var Magic = require('mmmagic').Magic;
var magic = new Magic();
var data = fs.readFileSync(path);
var image = new mongodb.Binary(data);
//open connection/collection
magic.detect(data,function(err,result) {
var record = {picname: id, content: image, mimeType: result };
collection.save(record, {safe: true}, function(err,result){
if(err)
console.log(err.stack);
});//save
});
Methods for writing the header vary, but with the base "http" for node you call as shown:
var record = {picname: id};
collection.findOne(record, function(err,result){
if(err)
console.log(err.stack);
else {
res.writeHead(200, {
'Content-Type': result.mimeType,
'Content-Length': result.content.length
});
res.write(result.content.buffer);
res.end();
}
});
So what effectively gets returned here is the binary data identified by it's correct mime type. So you can access this from an URL where you supply the means to lookup the document and view directly in a browser just as if it was a regular image file being served.
Related
I am new to Node.js and JavaScript. I have a results.json file that I want to keep a running log of results from a script that pulls images from the web. However, my current script only overwrites the existing result. How do I build upon or add to the results.json so each subsequent result is logged in the results.json file? I would like it to be valid json.
Here is general example:
var currentSearchResult = someWebSearchResult
var fs = require('fs');
var json = JSON.stringify(['search result: ' + currentSearchResult + ': ', null, "\t");
fs.writeFile("results.json", json);
And the results.json:
[
"search result: currentSearchResult"
]
If you want the file to be valid JSON, you have to open your file, parse the JSON, append your new result to the array, transform it back into a string and save it again.
var fs = require('fs')
var currentSearchResult = 'example'
fs.readFile('results.json', function (err, data) {
var json = JSON.parse(data)
json.push('search result: ' + currentSearchResult)
fs.writeFile("results.json", JSON.stringify(json))
})
In general, If you want to append to file you should use:
fs.appendFile("results.json", json , function (err) {
if (err) throw err;
console.log('The "data to append" was appended to file!');
});
Append file creates file if does not exist.
But ,if you want to append JSON data first you read the data and after that you could overwrite that data.
fs.readFile('results.json', function (err, data) {
var json = JSON.parse(data);
json.push('search result: ' + currentSearchResult);
fs.writeFile("results.json", JSON.stringify(json), function(err){
if (err) throw err;
console.log('The "data to append" was appended to file!');
});
})
Promise based solution [Javascript (ES6) + Node.js (V10 or above)]
const fsPromises = require('fs').promises;
fsPromises.readFile('myFile.json', 'utf8')
.then(data => {
let json = JSON.parse(data);
json.myArr.push({name: "Krishnan", salary: 5678});
fsPromises.writeFile('myFile.json', JSON.stringify(json))
.then( () => { console.log('Append Success'); })
.catch(err => { console.log("Append Failed: " + err);});
})
.catch(err => { console.log("Read Error: " +err);});
If your project supports Javascript ES8 then you could use asyn/await instead of native promise.
I have created data. Js file to maintain data displaying in the table fomat. Including text box to read data from user and how to display data enteted through text box in table
I'm still working on my SPA where can I track my expenses. Each Expense Item consists of a value, a date , description and tags.
The client send all these data to my server , where I want to save it in a JSON file.
My code looks like this right now:
(json.push isnt working)
client.on('message', function(value, date, descr, tags) {
console.log('message: ' + value, date, descr, tags );
var exp = new Object();
exp.id = id;
exp.value = value;
exp.date = date;
exp.tags = tags;
expArr[exp.id] = exp;
id++;
console.log(exp.id);
fs.readFile('expenses.json', function (err, data) {
var json = JSON.parse(data);
json.push(exp);
console.log(json);
fs.writeFile("expenses.json", JSON.stringify(exp),
function(err){
if (err) throw err;
console.log('The data was appended to file!');
});
})
});
My goal is, every newly added item should append to my JSON file.
In the end it should look like this for example:
{"expArray": [{"id":0,"value":"200","date":"dqwd","tags":"cnelw"},
{"id":1,"value":"300","date":"dqwd","tags":"ncjlekw"},
{"id":2,"value":"22","date":"dqwd","tags":"dnkqoe"}
]}
I dont know if it's necessary to to do an array there?
But I need to read the file again for the future and get the ID of the items to delete them on client-side or edit them.
Thanks for ur help!
try this:
client.on('message', function(value, date, descr, tags) {
console.log('message: ' + value, date, descr, tags );
// exp object
var exp = {id:id,value:value,date:date,tags:tags}
expArr[exp.id] = exp;
id++;
console.log(exp.id);
fs.readFile('expenses.json', function (err, data) {
var json = JSON.parse(data);
// _------- add expArray
json.expArray.push(exp);
console.log(json);
fs.writeFile("expenses.json", JSON.stringify(exp),
function(err){
if (err) throw err;
console.log('The data was appended to file!');
});
})
});
I am trying to write an import script in Nodejs that pulls data from the web and formats it and then sends it to my API.
Part of that includes pulling artist data from LastFM, fetching the images for each artist and sending them off to my API to resize and save.
The import script is just ran in terminal.
The part of the import script that is responsible for pulling the images down and sending off to my API looks like:
_.forEach(artist.images, function(image){
console.log('uploading image to server ' + image.url)
request.get(image.url)
.pipe(request.post('http://MyAPI/files/upload', function(err, files){
if (err) {
console.log(err);
}
console.log('back from upload');
console.log(files);
}));
});
And the files.upload action looks like:
upload: function(req, res){
console.log('saving image upload');
console.log(req.file('image'));
res.setTimeout(0);
var sizes = [
['avatar', '280x210'],
['medium', '640x640'],
['large', '1024x768'],
['square', '100x100'],
['smallsquare', '50x50'],
['avatarsquare', '32x32']
];
//resize to the set dimensions
//for each dimension - save the output to gridfs
_.forEach(sizes, function(bucket){
var width = bucket[1, 0], height = bucket[1, 2];
// Let's create a custom receiver
var receiver = new Writable({objectMode: true});
receiver._write = function(file, enc, cb) {
gm(file).resize(width, height).upload({
adapter: require('skipper-gridfs'),
uri: 'mongodb://localhost:27017/sonatribe.' + bucket[0]
}, function (err, uploadedFiles) {
if (err){
return res.serverError(err);
}
else{
return res.json({
files: uploadedFiles,
textParams: req.params.all()
});
}
});
cb();
};
/* req.file('image').upload(receiver, function(err, files){
if(err) console.log(err);
console.log('returning files');
return files;
});*/
});
}
However, console.log(req.file('image')); is not what I'd hope - probably because this code is expecting the image to be uploaded as part of a multi-part form upload with a field named image - which it is not...
I'm trying to figure out how the file will end up inside my action but my google foo is completely out of action today and I'm fairly (very) new to Node.
Anyone able to offer some pointers?
I'm currently building web using Sails.js and got stuck in retrieving image file from GridFS. I have successfully uploading the file using skipper-gridfs to my mongo gridfs. I have no idea to display the file in the correct way (I'm new in Sails.js and Node system)
Here is my code for retrieving image file from gridfs looks like in FileController.js (I'm using gridfs-stream):
show: function (req, res, next) {
var mongo = require('mongodb');
var Grid = require('gridfs-stream');
var buffer="";
// create or use an existing mongodb-native db instance
var db = new mongo.Db('testDb', new mongo.Server("192.168.0.2", 27017), {safe:true});
var gfs = Grid(db, mongo);
// streaming from gridfs
var readstream = gfs.createReadStream({
filename: 'e1ecfb02-e095-4e2f.png'
});
//check if file exist
gfs.exist({
filename: 'e1ecfb02-e095-4e2f.png'
}, function (err, found) {
if (err) return handleError(err);
found ? console.log('File exists') : console.log('File does not exist');
});
//buffer data
readstream.on("data", function (chunk) {
buffer += chunk;
console.log("adsf", chunk);
});
// dump contents to console when complete
readstream.on("end", function () {
console.log("contents of file:\n\n", buffer);
});
}
When I ran it, the console showed nothing.
There is no error either.
How should I fix this?
Additional Question:
Is it better & easier to store/read file to/from local disk instead of using gridfs?
Am I correct in choosing gridfs-stream to retrieve the file form gridfs?
In the skipper-gridfs codes and there's a 'read' method that accept fd value and returns the required file corresponding to that value. So, you just have to pull that file from mongo by that method and send as a response. It should work file.
download: function (req, res) {
var blobAdapter = require('skipper-gridfs')({
uri: 'mongodb://localhost:27017/mydbname.images'
});
var fd = req.param('fd'); // value of fd comes here from get request
blobAdapter.read(fd, function(error , file) {
if(error) {
res.json(error);
} else {
res.contentType('image/png');
res.send(new Buffer(file));
}
});
}
I hope it helps :)
Additional Questions:
Yes, using gridfs is better both in performance and efficiency. And normally mongodb has a limitation of 16MB probably for binary files, but using gridfs you can store any size file, it breaks them in chunks and stores them.
Retrieving has been shown above.
You can now use skipper-gridfs in sails to manage uploads/downloads.
var blobAdapter = require('skipper-gridfs')({uri: 'mongodb://jimmy#j1mtr0n1xx#mongo.jimmy.com:27017/coolapp.avatar_uploads' });
Upload:
req.file('avatar')
.upload(blobAdapter().receive(), function whenDone(err, uploadedFiles) {
if (err) return res.negotiate(err);
else return res.ok({
files: uploadedFiles,
textParams: req.params.all()
});
});
Download
blobAdapter.read(filename, callback);
Bear in mind the file name will change once you upload it to mongo, you have to use the file name returned in the first response.
I am using node-mongodb-native in my application. I send multiple POST requests to nodejs server to save/update each documents, but only one document is getting updated and all other document are not changing. The data received in the server is correct.
save : function(req,res) {
data = req.body;
if(!data._id){
data._id = new ObjectID();
}else{
data._id = ObjectID(data._id);
}
mColl(req.params.collname, function (collection,db) {
collection.save(data, {safe:true}, function(err, result) {
if(err){
res.send(err);
}
else {
res.send(result);
}
});
});
}
I am not getting the response for the request also.
For starters, don't do this:
data = req.body;
When a new request comes in, you're overwriting the (global!) data variable, and all kinds of undefined stuff can happen. So always declare a new variable:
var data = req.body;