Stream a file from NodeJS - node.js

I am using weed-fs to store files and trying to stream file to client using below code
var fileName = [__dirname, '/uploads/', req.params.id, ".png"].join('');
try {
var writeStream = fs.createWriteStream(fileName);
weedfs.read(req.params.id, writeStream);
writeStream.on("close", function () {
var readStream = fs.createReadStream(fileName);
response.pipe(readStream);
response.on('error', function (err) {
readStream.end();
});
response.on('end', function (err) {
removeFile(fileName);
});
});
} catch (e) {
res.send(404);
}
But I am getting error Error: connect ECONNREFUSED
If I look at the weedfs read method, I found below code
read: function(fid, stream, cb) {
var ins = this;
if ((typeof stream == "function") && !cb) {
cb = stream;
stream = false;
}
this.find(fid, function(pub) {
if (pub[0]) {
if (stream) {
ins.http(pub[0]).pipe(stream);
......
Am I doing something wrong. Please help me to fix this issue.

Related

How to make express download link with GridFsBucket?

As the title says, how do you make a direct download link with a file from mongoDB(GridFsBucket) using express?
The file should be downloadable from memory, as i dont want to save it temporarily on the server.
I have this method:
async function downloadFileFromDB(fileId) {
var gridfsbucket = new mongoose.mongo.GridFSBucket(mongoose.connection.db, {
chunkSizeBytes: 1024,
bucketName: 'filesBucket'
});
try {
const stream = gridfsbucket.openDownloadStream(fileId)
const fileBuffer = Buffer.from(stream)
return fileBuffer
} catch (err) {
stream.on('error', () => {
console.log("Some error occurred in download:" + error);
})
console.log(err);
}
}
And this route:
router.get('/download-file', async (req,res) => {
const fileId = req.query.fileId
const ObjectFileId = new ObjectId(fileId)
const fileBuffer = await fileFacade.downloadFileFromDB(ObjectFileId)
res.download(fileBuffer)
})
But res.download wants a path and not a buffer. Aswell im not sure i can make a buffer directly from the openDownloadStream method.
Can anyone help?
I believe you need to write the data to your res object. I accomplished this like:
const readStream = gridfs.openDownloadStreamByName(filename);
readStream.on("data", (chunk) => {
res.write(chunk);
});
readStream.on("end", () => {
res.status(200).end();
mongoClient.close();
});
readStream.on("error", (err) => {
console.log(err);
res.status(500).send(err);
});
So, you may just have to do:
res.write(fileBuffer).end();
//// Instead of doing:
// res.download(fileBuffer);

Nodejs: ENOENT on Twitter Image Bot

I'm a beginner level programmer. I used some online guides as well as my starter knowledge. I'm attempting to create a bot that posts to twitter every hour. I keep getting the error ENOENT, which as I understand, means that it can't find the directory. Here is the error I'm getting (All I censored was personal information, but it's not censored in the actual code or error)
opening an image...
15.jpg
internal/fs/utils.js:269
throw err;
^
Error: ENOENT: no such file or directory, open 'C:\Users\####\Desktop\####\bot\images15.jpg'
at Object.openSync (fs.js:462:3)
at Object.readFileSync (fs.js:364:35)
at C:\Users\####\Desktop\####\bot\server.js:32:29
at FSReqCallback.oncomplete (fs.js:156:23) {
errno: -4058,
syscall: 'open',
code: 'ENOENT',
path: 'C:\\Users\\#####\\Desktop\\####\\bot\\images15.jpg'
}
It looks like its changing the name of the file to have images in front. I can't figure out why it's doing this though. Anyone know what I'm doing wrong? Here's my code:
const fs = require('fs'),
path = require('path'),
Twit = require('twit'),
config = require(path.join(__dirname, 'config.js')),
images = require(path.join(__dirname, 'images.js'));
const T = new Twit(config);
function randomFromArray(images) {
return images[Math.floor(Math.random() * images.length)];
}
function tweetRandomImage() {
fs.readdir(__dirname + '/images', function (err, files) {
if (err) {
console.log('error:', err);
}
else {
let images = [];
files.forEach(function (f) {
images.push(f);
});
console.log('opening an image...');
const image = randomFromArray(images);
console.log(image);
const imagePath = path.join(__dirname, '/images' + image);
const imageSource = image.source
b64content = fs.readFileSync(imagePath, { encoding: 'base64' });
console.log('uploading an image...');
T.post('media/upload', { media_data: b64content }, function (err, data, response) {
if (err) {
console.log('error:', err);
}
else {
console.log('image uploaded, now tweeting it...');
T.post('statuses/update', {
media_ids: new Array(data.media_id_string)
},
function (err, data, response) {
if (err) {
console.log('error:', err);
}
else {
console.log('posted an image!');
}
}
);
}
});
}
});
}
setInterval(function () {
tweetRandomImage();
}, 10000);
Any help would be appreciated, thank you!
lesson of the day, ALWAYS WATCH THE SynTAx
const fs = require('fs'),
path = require('path'),
Twit = require('twit'),
config = require(path.join(__dirname, 'config.js')),
images = require(path.join(__dirname, 'images.js'));
const T = new Twit(config);
function randomFromArray(images) {
return images[Math.floor(Math.random() * images.length)];
}
function tweetRandomImage() {
fs.readdir(__dirname + '/images', function (err, files) {
if (err) {
console.log('error:', err);
}
else {
let images = [];
files.forEach(function (f) {
images.push(f);
});
console.log('opening an image...');
const image = randomFromArray(images);
console.log(image);
//THE ONLY CHANGE I MADE BELOW
const imagePath = path.join(__dirname, '/images/' + image);
//THE ONLY CHANGE I MADE ABOVE
//THE ONLY PROBLEM WAS THAT YOU TRIED GETTING A FILE BUT HAVING A FOLDER AND A FILE NAME AS 1 THING UNSEPARATED BY "/" OR "\\" AND THE COMPUTER(& me who read it at first) THOUGHT TO LOOK FOR A FILE CALLED "images15.jpg" instead of "images/15.jpg"
const imageSource = image.source
b64content = fs.readFileSync(imagePath, { encoding: 'base64' });
console.log('uploading an image...');
T.post('media/upload', { media_data: b64content }, function (err, data, response) {
if (err) {
console.log('error:', err);
}
else {
console.log('image uploaded, now tweeting it...');
T.post('statuses/update', {
media_ids: new Array(data.media_id_string)
},
function (err, data, response) {
if (err) {
console.log('error:', err);
}
else {
console.log('posted an image!');
}
}
);
}
});
}
});
}
setInterval(function () {
tweetRandomImage();
}, 10000);

Use Firebase Function with error TypeError

I am very new to Node js, I just want to get the data from extenal xml from a website but I got an error from Firebase Function log TypeError: invalid media type. I think it come from when I try to do this task parseString(xml, function(err, result) { })
Anyone can help me, it will be great:
Here is my code on firebase function:
exports.getRate = functions.https.onRequest((req, res) => {
getRate = () => {
var url = "https://www.vietcombank.com.vn/ExchangeRates/ExrateXML.aspx";
https.get(url, function(res) {
var xml = "";
res.on('error', function(error){
console.log(error, 'get data error');
})
res.on("data", function(chunk) {
xml += chunk;
console.log(xml, 'xml file');
});
res.on("end", function() {
var date = "";
let rateAUD = {
code: 'AUD/VND',
buy: 0,
sell: 0
};
let rateUSD = {
code: 'USD/VND',
buy: 0,
sell: 0
};
parseString(xml, function(err, result) {
console.log(xml, 'xml file');
date = result.ExrateList.DateTime[0];
if (result.ExrateList.Exrate[0].$.CurrencyCode == "AUD") {
rateAUD.buy = result.ExrateList.Exrate[0].$.Buy;
rateAUD.sell = result.ExrateList.Exrate[0].$.Sell;
} else {
console.log("They change the database list");
}
if (result.ExrateList.Exrate[18].$.CurrencyCode == "USD") {
rateUSD.buy = result.ExrateList.Exrate[18].$.Buy;
rateUSD.sell = result.ExrateList.Exrate[18].$.Sell;
} else {
console.log("They change the database list");
}
console.log(rateAUD, rateUSD, 'get data');
uploadDataToServer(date, { rateAUD, rateUSD });
if(err) {
console.log(err);
}
});
});
});
};
function uploadDataToServer(date, { rateAUD, rateUSD }) {
var db = admin.firestore();
let data = { rateAUD, rateUSD };
data.timeStamp = date;
console.log('upload success');
db.collection("liveRate").add(data),then((err)=> {
console.log(err);
});
}
return res.status(200)
.type('application / json')
.send('hello')
});
'
When I run the same code on another Nodejs playground, it works well.
Here is the link: https://repl.it/repls/MaroonSlateblueProfiler
So weird!
Ps: my payment option is ON.
The problem is that the client is sending the server what may or may not be a valid media type in an encoding the server cannot understand (as per the Content-Encoding header the client packaged with the request message).
Please try to set the content-type to xml:
getRate = () => {
var options = {
hostname: "www.vietcombank.com.vn",
port: 443,
path: "/ExchangeRates/ExrateXML.aspx",
headers: {
'Content-Type': 'application/xml'
}
};
https.get(options, function(res) {
...
});
}

Upload image from buffer in request

I am trying to handle a image upload request from an iOS/Android app. In the request I am getting a buffer of the image and want to upload that to Rackspace files without having to download the image to re-upload it. I could write the file to file system and read from that but I want to know if it is possible to create a readableStream with the buffer in order to pipe that to cloud.
var options = {
container: _this3._container,
remote: filename,
contentType: contentType
}
var readStream = new Readable(data);
readStream._read();
readStream.on('data', function() {
console.log("Has data!");
});
function upload() {
return new Promise(function (resolve, reject) {
var writeStream = _this3._RackClient.upload(options);
writeStream.on('success', function() {
resolve();
});
writeStream.on('error', function(err) {
if (err !== null) {
return reject(err);
}
});
readStream.pipe(writeStream);
});
}
return upload();
Is how I am currently trying to do it but I continue to get not implemented errors.
I was actually able to achieve this using a PassThrough stream.
var options = {
container: _this3._container,
remote: filename,
contentType: contentType
};
function upload() {
return new Promise(function (resolve, reject) {
var writeStream = _this3._RackClient.upload(options);
var bufferStream = new stream.PassThrough();
bufferStream.end(new Buffer(data));
writeStream.on('success', function(file) {
resolve(file);
});
writeStream.on('error', function(err) {
if (err !== null) {
console.log(err);
return reject(err);
}
});
bufferStream.pipe(writeStream);
});
}
return upload();

Unable to send a response while multipart form is being streamed

I'm using nodejs combined with sailsjs and skipper to upload files to a server.
I have a use case where I need to check the file length and send a 413 error if the upload exceeds A certain file size. However when I try send any kind of response nothing happens. What exactly is happening here? Does the form upload need to be completed before a response can be sent?
var getReceiver = function () {
var receiver = new Writable({objectMode: true});
receiver._write = function (file, enc, done) {
file.fd = directory + file.fd;
var fileStream = fs.createWriteStream(file.fd);
fileStream.on('error', function (err) {
done(err);
}).once('finish', function () {
done();
});
var fileLength = 0;
file.on('data', function (chunk) {
fileLength = fileLength + chunk.length;
if (fileLength > maxFileSize) {
var err = new Error('upload exceeds maxFileSize.');
file.unpipe();
fs.unlink(file.fd, function (fsErr) {
if (fsErr && (typeof fsErr !== 'object' || fsErr.code !== 'ENOENT')) {
return done([err].concat([fsErr]));
}
});
return done(err);
}
});
file.pipe(fileStream);
};
return receiver;
};
req.file('file').upload(getReceiver(), function (err, uploadedFiles) {
if (err) {
return res.badRequest(err);
}
// Do stuff
}
});
});
});

Resources