Download a file with Angular.js and Express.js

15,802 views
Skip to first unread message

Smart Cris

unread,
Apr 14, 2014, 11:14:51 AM4/14/14
to ang...@googlegroups.com

This time I got bad luck with Stack Overflow, you guys are my last resource, and pls be kind with a newbie. Here is the trouble: in my MEAN application I need to provide a link to download a file (tif image), the link must be hidden and not accessible by unauthorized users. So I came up with the idea of keeping the files inside the server directory and let Angular.js send with ng-click="download()" an $HTTP request to express.js with the file ID to download. Here is my code that doesn't work, there are no errors whatsoever, but I can't even get the download dialog box to open:

Client Side:

$scope.download=function(){
$http({method:'GET', url:'/download/'+image[0]['_id']}).
  success(function(data, status, headers, config) {         
    var element = angular.element('<a/>');
     element.attr({
         href: 'data:attachment/tif;charset=utf-8,' + encodeURI(data),
         target: '_self',
         download:'test.tif'
     })[0].click();
   }).
  error(function(data, status, headers, config) {
   });
  }

Template:

<a ng-href="#" target="_self" type="button" class="btn" ng-click="download()">Download</a>

Server Side

app.namespace('/download/:documentID*', function() {

app.all('/', function(req, res, next){
  res.download('images/download/test.tif', 'test.tif', function(err){
  if (err) {
   } else {
     next();
      }
    });
  });
})

squi...@gmail.com

unread,
Apr 14, 2014, 1:00:52 PM4/14/14
to ang...@googlegroups.com
I think you are making this too complicated. All you should need to do is to create a link to the file (place the URL you're using in the AJAX request in the href of the link instead) and then have your Express code "strongly encourage" the client to download the file rather than display it. Take a look at https://stackoverflow.com/questions/10615797/utility-of-http-header-content-type-application-force-download-for-mobile for some information. Basically, add the Content-Disposition: attachment; etc etc header to the response with the file. Don't forget that just because a user can't see a link, that doesn't mean they can't access a URL. This means that you need to validate on the server side that they are authorized to access the file even if they were able to ping the URL.

Smart Cris

unread,
Apr 14, 2014, 3:01:27 PM4/14/14
to ang...@googlegroups.com
Thx for the suggestion,  a simple <a ng-href="{{file}}" target="_self"></A> did the job without even touching the headers.

Ziobudda

unread,
Apr 14, 2014, 10:39:36 PM4/14/14
to ang...@googlegroups.com

Il giorno 14/apr/2014, alle ore 21:01, Smart Cris <cmwebcr...@gmail.com> ha scritto:

Thx for the suggestion,  a simple <a ng-href="{{file}}" target="_self"></A> did the job without even touching the headers.


In this way your file is accessible to unauthorized users. They need to know only the “file” url. 
Or your {{file}} is something like "/download/ID_IMAGE” ? 

M.
--
Davide Morelli




Smart Cris

unread,
Apr 15, 2014, 4:39:32 AM4/15/14
to ang...@googlegroups.com
My link show only part of the url, but Imho there is no solution to keep things safe on the client side, even with a simple "/download/ID_IMAGE" a malicious user can easily rebuild the protected link, the best approach in SPA application is to send encrypted username and password for every type of request.

Ziobudda

unread,
Apr 15, 2014, 10:39:48 PM4/15/14
to ang...@googlegroups.com
Il giorno 15/apr/2014, alle ore 10:39, Smart Cris <cmwebcr...@gmail.com> ha scritto:

My link show only part of the url, but Imho there is no solution to keep things safe on the client side, even with a simple "/download/ID_IMAGE" a malicious user can easily rebuild the protected link,

One thing is rebuild the protected link, another is that the protected link send the image to the client and not the web server.

If your backend can intercept the file request (client browser does not request the original file but a “/download/ID_IMAGE”) then it can check if the user has the permission to access to that file and so it is useless know the protected link. No file is send without permission. 
And if the user can access the file, the backend does not redirect him (browser) to the original file but send the file to him. It is different. 

Trishna Pampari

unread,
Jan 9, 2017, 2:02:08 AM1/9/17
to Angular, cmwebcr...@gmail.com

hi can i know whats is {{file}} and how you are downloading file.

Sander Elias

unread,
Jan 9, 2017, 2:37:16 AM1/9/17
to Angular, cmwebcr...@gmail.com
Hi Trishna,

Probably the url to the server endpoint providing the raw data for the file.

Regards
Sander
Reply all
Reply to author
Forward
0 new messages