1

I am currently learning node.js, and recently came across a situation where I'd like to download an image stored on the server upon clicking a button on the webpage. I have created an endpoint, to which the controller passes two arguments:
- Name of the image to be downloaded (the directory is fixed)
- Name by which to download the image

I have tried the solutions given in Download a file from NodeJS Server using Express

I'm using angular to populate the buttons and trigger the download, as follows:

<div class="btn-group" role="group" aria-label="Image tags">
    <button ng-repeat="tag in imageTags" type="button" class="btn btn-outline-warning" ng-click="download(tag)">{{tag}}</button>
</div>

And here is my controller:

$scope.download = function(tagName) {
    tagName = tagName.replace(/\W+/g, '-');
    Clarifai.download(tagName, UploadSuccess.uploadedFile)
        // UploadSuccess.uploadedFile contains the name of the file to be downloaded.
        .success(function(data) {
            //do something
        });
}

which calls the following factory method:

download: function(tagName, imageName) {
    return $http.get('/api/clarifai/tagDownload/' + tagName + "/" + imageName);
}

And here's the relevant part of my routes file:

app.get('/api/clarifai/tagDownload/:tagName/:imageName', function(req, res) {
    // Ignore tagName for now.
    console.log("Begin download");
    var img = path.resolve('image_dump/OutputDump/' + req.params.imageName);
    // Returns the expected path for the file
    var filename = path.basename(img);
    var mimetype = mime.lookup(img);

    console.log(filename);
    console.log(mimetype);

    res.setHeader('Content-disposition', 'attachment; filename=' + filename);
    res.setHeader('Content-type', mimetype);

    var filestream = fs.createReadStream(img);
    filestream.pipe(res);
    res.on('finish', function(){
        console.log("Download complete");
    });
});

So all the flow works till this point, and upon clicking one of the buttons, I get the output as follows:

Begin download
Jon-1477683540996.jpg
image/jpeg
GET /api/clarifai/tagDownload/people/Jon-1477683540996.jpg 200 5.296 ms -
Download complete

But I see no sign of the downloaded file anywhere. No dialogs on any browser. All answers I've read so far seem to mention that the download is handled by the pipe call. But with no success for me.

I have also tried res.download(img), but with the same results.

My approach has been to handle this using the callback inside the controller. But I'm unable to figure out how to do so. What am I missing / doing wrong? Can somebody please point me in the right direction?

Thank you in advance.

Community
  • 1
  • 1
Naresh R
  • 11
  • 1
  • 4
  • If you're using Express, you should be able to just do `res.download('image_dump/OutputDump/' + req.params.imageName)` – adeneo Oct 28 '16 at 20:35
  • @adeneo, I have tried that. But with no luck. No download dialogs. File is not present in my default downloads directory either. – Naresh R Oct 28 '16 at 20:46
  • If you just type the URL in the browser, does it start a download then? Buttons don't generally redirect, neither does Angular ? – adeneo Oct 28 '16 at 20:49
  • Ouch. That did the trick! Thanks a ton! – Naresh R Oct 28 '16 at 21:05

1 Answers1

0

For the sake of completeness, here's how I solved the problem:
In my controller, instead of using:

$http.get('/api/clarifai/tagDownload/' + tagName + "/" + imageName);

I had to do:

path = "/api/clarifai/tagDownload/" + tagName + "/" + imageName;
$window.location.href = path;

As adeneo had pointed out, the reason to this was that clicking on a button in Angular doesn't redirect. So, this had to be manually triggered using Angular's $window.location.href API.

Some alternate ways to do this can also be found in this answer: Using $window or $location to Redirect in AngularJS

Naresh R
  • 11
  • 1
  • 4