Last ned en fil med jQuery.Ajax

Jeg har en Struts2-handling på serversiden for nedlasting av filer.

<action name="download" class="com.xxx.DownAction">
    <result name="success" type="stream">
        <param name="contentType">text/plain</param>
        <param name="inputName">imageStream</param>
        <param name="contentDisposition">attachment;filename={fileName}</param>
        <param name="bufferSize">1024</param>
    </result>
</action>

Men når jeg kaller handlingen ved hjelp av jQuery:

$.post(
  "/download.action",{
    para1:value1,
    para2:value2
    ....
  },function(data){
      console.info(data);
   }
);

i Firebug ser jeg at dataene hentes med Binary stream. Jeg lurer på hvordan jeg åpner filnedlastingsvinduet som brukeren kan lagre filen lokalt med?

Løsning

2019 oppdatering av moderne nettlesere

Dette er tilnærmingen jeg nå vil anbefale, med noen få forbehold:

  • En relativt moderne nettleser er nødvendig
  • Hvis filen forventes å være veldig stor, bør du sannsynligvis gjøre noe som ligner på den opprinnelige tilnærmingen (iframe og informasjonskapsel) fordi noen av operasjonene nedenfor sannsynligvis kan forbruke systemminne minst like stort som filen som lastes ned og/eller andre interessante CPU-bivirkninger.
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!'));

Original jQuery/iframe/Cookie-basert tilnærming fra 2012.

Bluish har helt rett i dette, du kan ikke gjøre det via Ajax fordi JavaScript ikke kan lagre filer direkte på en brukers datamaskin (av sikkerhetshensyn). Dessverre betyr det å peke hovedvinduets nettadresse mot filnedlastingen at du har liten kontroll over brukeropplevelsen når en fil lastes ned.

Jeg opprettet jQuery File Download som gir en "Ajax-lignende" opplevelse med filnedlastinger komplett med OnSuccess og OnFailure callbacks for å gi en bedre brukeropplevelse. Ta en titt på mitt blogginnlegg om det vanlige problemet som pluginet løser og noen måter å bruke det på, og også en demo av jQuery File Download i aksjon. Her er kilden

Her er en enkel brukstilfelle demo ved hjelp av plugin kilde med løfter. Demosiden]7 inneholder også mange andre og bedre UX-eksempler.

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

Avhengig av hvilke nettlesere du trenger å støtte, kan du kanskje bruke https://github.com/eligrey/FileSaver.js/ som gir mer eksplisitt kontroll enn IFRAME-metoden jQuery File Download bruker.

Kommentarer (16)

Ingen har lagt ut denne @Pekkas løsning... så jeg legger den ut. Det kan hjelpe noen.

Du trenger ikke å gjøre dette gjennom Ajax. Bare bruk

window.location="download.action?para1=value1...."
Kommentarer (8)

1. Framework agnostic: Servlet laster ned fil som vedlegg.


<a href="javascript:window.location='downloadServlet?param1=value1'">
    download
</a>


<a href="downloadServlet?param1=value1" >download</a>

2. Struts2-rammeverk: Handling nedlasting av fil som vedlegg


<a href="javascript:window.location='downloadAction.action?param1=value1'">
    download
</a>


<a href="downloadAction.action?param1=value1" >download</a>

Det ville være bedre å bruke -taggen som peker med *OGNL* til en *URL* opprettet med-taggen:




    value1
Kommentarer (3)