0

I've tried to download this image a million ways and I always get an undefined value in NodeJS, can someone please help me!! The image does download, but I cannot do anything with it, so it essentailly becomes useless!

var rawImg = urlHtml('img').attr('src'); // got the image needed!                                


                            var download = function (rawImg, filename, callback) {
                                request.head(rawImg, function (err, res, body) {
                                    console.log('content-type:', res.headers['content-type']);
                                    console.log('content-length:', res.headers['content-length']);

                                    request(rawImg).pipe(fs.createWriteStream(__dirname + '/public/img/test.jpg')).on('close', function(callback) {

                                        console.log(callback); // always getting undefined
                                    });
                                });
                            };

                            download(rawImg, function () {
                                console.log('done'); // doesn't even launch because gets undefined before
                            });

3 Answers3

0

Below is some sample code that downloads and saves an image to your hard drive. Here are some of the reasons why it is different from your code:

  1. I am not sure what function urlHtml is, but my guess is that the rawImg variable is actually just the src attribute on an img html element. If that is the case, then rawImg is actually just a string with the image's URL in it. This is why, in my example code, I have renamed that variable in my code to be url.
  2. Your function download expects three parameters (rawImg, filename, and callback), but you only call the function with two parameters (rawImg and a callback function). Since no filename is provided, your download function thinks that the function you intended to be a callback function is actually the filename. And since there is no third argument, callback is undefined.
  3. Using the request.head function will only retrieve the HTTP headers without the body. So you won't actually get the image bytes with an HTTP HEAD request. See [https://ochronus.com/http-head-request-good-uses/ this article] for more details on HTTP HEAD. Since we are interested in downloading the image itself, we should perform an HTTP GET insted of an HTTP Head. This is why my sample code calls request.get.
  4. .on('close', function(callback) {...}) is incorrect because the on-close function will not be called with any parameters when the close event is triggered. So callback is undefined because it is not passed into the function when the close event fires. This is why, in my example, there is no callback parameter for the on-close function.

Note 1: My example code adds some require calls for completeness, since this question is tagged as a nodejs question. It looks like you already have the fs and request variables in scope, so you may not need to require them again.

Note 2: If you are getting the URL from your urlHtml('img').attr('src'); call, then replace the hardcoded url in my code with urlHtml('img').attr('src');.

Working, example code (tested and all!!):

var fs = require('fs')
var request = require('request')

var url = 'https://avatars0.githubusercontent.com/u/5980429?v=2&s=200'

var download = function (url, filename, callback) {
    request.get(url).pipe(fs.createWriteStream(__dirname + '/' + filename)).on('close', function() {
        callback()
    })
};

download(url, 'image.png', function () {
    console.log('Image downloaded successfully. It is now saved in a file called "image.png" in the current working directory!');
});
Joel Denning
  • 460
  • 1
  • 3
  • 13
  • ya rawImg is suppose to be the actual source, now it's saying that my actual URL is undefined –  Oct 09 '14 at 11:16
  • The site that I'm getting theimage from uses the "https" protocol, maybe this is the cause?? –  Oct 09 '14 at 11:36
  • https should not be a problem. Does your first comment mean that rawImg is supposed to be the image bytes? Because `src` usually refers to the URL, not the image bytes. . I guess this all depends on what the `urlHtml` function is doing. Is that a function you defined? Or is it part of a different nodejs library? – Joel Denning Oct 09 '14 at 15:41
  • Well I'm using the cheerio module to grab the image thats where I get the urlHtml value from, it loads the page as html. When I console.log rawImg I get the actual image URL. I have no problem downloading it to file, but I can't do anything with it. –  Oct 09 '14 at 18:06
  • When you say that you "can't do anything with it", do you mean that you would like to do something to the image bytes, instead of saving the image to disk? If that is the case, then you have two options: (1) Write it to disk and then reopen it in your callback function, or (2) Provide a different [Writable](http://nodejs.org/api/stream.html#stream_class_stream_writable) instead of `fs.createWriteStream`. Check out the documentation at http://nodejs.org/api/stream.html#stream_readable_pipe_destination_options to learn about writable streams – Joel Denning Oct 09 '14 at 19:33
  • What I mean by "can't do anything with it" I want to immediately create a ReadStream right after. I've written it to disk and it saves, but when I pipe it to a ReadStream it says it's not there. I'm starting to think that it's my web scraper that's causing the problem (Cheerio.js). –  Oct 09 '14 at 21:03
  • Maybe the answer to a similar question will help: http://stackoverflow.com/questions/17098400/how-to-chain-write-stream-immediately-with-a-read-stream-in-node-js-0-10 – Joel Denning Oct 10 '14 at 06:14
  • I saw that one before, just gave me more questions than answers –  Oct 19 '14 at 19:17
0

request(rawImg).pipe( fs.createWriteStream(__dirname + '/public/img/test.jpg')).on('close',function(callback) { console.log(callback); // always getting undefined });

Replace the bolded line with callback();

The 'undefined' value you are seeing is the return value of console.log.

randominstanceOfLivingThing
  • 16,873
  • 13
  • 49
  • 72
  • I still get an 'undefined' error, but now I realized it's my cheerio module thats causing it, but thanks! –  Oct 10 '14 at 01:38
0

For anyone wondering, I figured out what my problem was. I was trying to download what was in a nested object. Ended up using underscore.js !!