简体   繁体   中英

Download file when clicking on the link in Meteor

I store the mp3 files on my server using https://github.com/CollectionFS/Meteor-CollectionFS . I want to allow user to download the file just by clicking on the link and the 'download' attribute should work fine here ie:

 <a href="/cfs/files/audio/ubcq5Xev4mkQ3sv5t/file.mp3" download="file.mp3">download</a>

The problem is that the file is opening/playing in the browser instead of just start to downloading to disk.

As discussed here https://code.google.com/p/chromium/issues/detail?id=373182 I guest it is because of cross origin request, so I tried to follow the suggested solution and use this link

<a href="#" download data-url="{{url}}" type="button" class="btn btn-default">download</a>

with this handler

Template.podcastItemSummary.events({
    'click a.btn-download': function(event, instance){
        event.preventDefault();            
        downloadFile($(event.currentTarget).attr('data-url'));
    }
});

if (Meteor.isClient) {
    downloadFile = function(sUrl){
        window.URL = window.URL || window.webkitURL;
        var xhr = new XMLHttpRequest();
        xhr.open('GET', sUrl, true);
        xhr.responseType = 'blob';
        xhr.onload = function(e) {
            var res = xhr.response;               
            var blob = new Blob([res], {type:"audio/mp3"});
            url = window.URL.createObjectURL(blob);
            var a = document.createElement("a");
            a.style.display = "none";
            a.href = url;            
            a.download = sUrl.split('/').pop();
            document.body.appendChild(a);
            a.click();
            window.URL.revokeObjectURL(url);
        };
        xhr.send();
    }
}

Now the file is downloaded as expected, but for large files there is a strange delay between 'click' and start of download. Any better solution?

As @ZuzEL wrote, the solution is to just end the link with ?download

<a href="/cfs/files/audio/ubcq5Xev4mkQ3sv5t/file.mp3?download" target="_parent">download</a>

I stored the url in a separate collection, and now I realized that I should store only the file's id (ubcq5Xev4mkQ3sv5t) as there is a by design solution https://github.com/CollectionFS/Meteor-CollectionFS/wiki/How-to:-Provide-a-download-button

Template.fileList.helpers({
  files: function () {
    return Files.find();
  }
});

and template

<template name="fileList">
  <div class="fileList">
    {{#each files}}
      <div class="file">
        <strong>{{this.name}}</strong> <a href="{{this.url download=true}}" class="btn btn-primary" target="_parent">Download</a>
      </div>
    {{/each}}
  </div>
</template>

which produces an url that includes a token as well

<a href="/cfs/files/audio/WdBfMy2gSLRwx3XKw/file.mp3?token=eyJhdXRoVG9rZW4iOiJ2bHd6WGNoT3ktUzNoOTJUUHJnLXFMZDd6OE9yS3NHMFNkaGMwbTRKWVVUIn0%3D&amp;download=true" target="_parent">Download</a>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM