This feels like an obvious question but it's perplexing me: I want a Node function that downloads a resource at a URI. I need it to work for several different content types without the user needing to specify which type it is.
I know how to pipe request
to fs.createWriteStream
when you know it's going to be an image, but not how to handle it when you've already invoked the callback from request. Here's where I am:
var request = require('request'),
fs = require('graceful-fs');
function cacheURI(uri, cache_path, cb) {
request(uri, function(err, resp, body) {
var content_type = resp.headers['content-type'].toLowerCase().split("; ")[0],
type = content_type.split("/")[0],
sub_type = content_type.split("/")[1];
if (sub_type == "json") {
body = JSON.parse(body);
}
if (type == "image") {
// this is where the trouble starts
var ws = fs.createWriteStream(cache_path);
ws.write(body);
ws.on('close', function() {
console.log('image done');
console.log(resp.socket.bytesRead);
ws.end();
cb()
});
} else {
// this works fine for text resources
fs.writeFile(cache_path, body, cb);
}
});
}
This answer to a previous question suggests the following:
request.get({url: 'https://someurl/somefile.torrent', encoding: 'binary'}, function (err, response, body) {
fs.writeFile("/tmp/test.torrent", body, 'binary', function(err) {
if(err)
console.log(err);
else
console.log("The file was saved!");
});
});
But I can't pass "binary" to request
if I don't yet know the type of response I'll get.
UPDATE
Per the suggested answer, changing "close" to "finish" in the event handler does fire the callback:
if (opts.image) {
var ws = fs.createWriteStream(opts.path);
ws.on('finish', function() {
console.log('image done');
console.log(resp.socket.bytesRead);
});
//tried as buffer as well
//ws.write(new Buffer(body));
ws.write(body);
ws.end();
}
This does write the image file, but not correctly: