Bestand downloaden met behulp van Javascript/jQuery

Ik heb een zeer vergelijkbare eis gespecificeerd hier.

Ik moet de browser van de gebruiker's handmatig een download laten starten wanneer $('a#someID').click();

Maar ik kan de window.href methode niet gebruiken, omdat het de huidige pagina inhoud vervangt met het bestand dat je'probeert te downloaden.

In plaats daarvan wil ik de download openen in een nieuw venster/tabblad. Hoe is dit mogelijk?

Oplossing

Gebruik een onzichtbare <iframe>:


<script>
function Download(url) {
    document.getElementById('my_iframe').src = url;
};
</script>

Om de browser te dwingen een bestand te downloaden dat hij anders wel zou kunnen renderen (zoals HTML of tekstbestanden), moet de server het MIME Type van het bestand op een onzinnige waarde zetten, zoals application/x-please-download-me of als alternatief application/octet-stream, dat gebruikt wordt voor willekeurige binaire gegevens.

Als je het alleen in een nieuw tabblad wilt openen, is de enige manier om dit te doen dat de gebruiker op een link klikt waarvan het target attribuut is ingesteld op _blank.

In jQuery:

$('a#someID').attr({target: '_blank', 
                    href  : 'http://localhost/directory/file.pdf'});

Telkens wanneer op die link wordt geklikt, wordt het bestand gedownload in een nieuw tabblad/venster.

Commentaren (21)

2019 moderne browsers update

Dit is de aanpak die ik nu zou aanbevelen met een paar voorbehouden:

  • Een relatief moderne browser is vereist
  • Als het bestand naar verwachting zeer groot is, moet je waarschijnlijk iets soortgelijks doen als de oorspronkelijke aanpak (iframe en cookie), omdat sommige van de onderstaande bewerkingen waarschijnlijk systeemgeheugen zouden kunnen verbruiken dat minstens zo groot is als het bestand dat wordt gedownload en/of andere interessante CPU neveneffecten.
fetch('https://jsonplaceholder.typicode.com/todos/1')
  .then(resp => resp.blob())
  .then(blob => {
    const url = window.URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.style.display = 'none';
    a.href = url;
    // the filename you want
    a.download = 'todo-1.json';
    document.body.appendChild(a);
    a.click();
    window.URL.revokeObjectURL(url);
    alert('your file has downloaded!'); // or you know, something with better UX...
  })
  .catch(() => alert('oh no!'));

2012 originele jQuery/iframe/cookie gebaseerde aanpak

Ik heb de jQuery File Download plugin (Demo) (GitHub) gemaakt die ook zou kunnen helpen met jouw situatie. Het werkt ongeveer hetzelfde met een iframe, maar heeft een aantal coole functies die ik erg handig vond:

  • Zeer eenvoudig op te zetten met mooie visuals (jQuery UI Dialog, maar niet vereist), alles is ook getest

  • De gebruiker verlaat nooit dezelfde pagina vanwaar hij een bestand heeft gedownload. Deze functie wordt steeds belangrijker voor moderne webapplicaties

  • SuccessCallback en failCallback functies zorgen ervoor dat je expliciet kan zijn over wat de gebruiker ziet in beide situaties

  • In combinatie met jQuery UI kan een ontwikkelaar eenvoudig een modal tonen die de gebruiker vertelt dat er een file wordt gedownload, de modal weer uitschakelen nadat de download is gestart of zelfs de gebruiker op een vriendelijke manier informeren dat er een fout is opgetreden. Zie de Demo voor een voorbeeld hiervan. Hopelijk helpt dit iemand!

Hier is een eenvoudige use case demo die gebruik maakt van de plugin source met beloftes. De demo pagina bevat ook vele andere, 'betere UX' voorbeelden.

$.fileDownload('some/file.pdf')
    .done(function () { alert('File download a success!'); })
    .fail(function () { alert('File download failed!'); });
Commentaren (10)

Als je al jQuery gebruikt, kun je daar gebruik van maken om een kleiner knipsel te maken Een jQuery versie van Andrew's antwoord:

var $idown;  // Keep it outside of the function, so it's initialized once.
downloadURL : function(url) {
  if ($idown) {
    $idown.attr('src',url);
  } else {
    $idown = $('<iframe>', { id:'idown', src:url }).hide().appendTo('body');
  }
},
//... How to use it:
downloadURL('http://whatever.com/file.pdf');
Commentaren (7)