Serverio pusėje turiu Struts2 veiksmą, skirtą failų atsisiuntimui.
<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>
Tačiau kai iškviečiu veiksmą naudodamas jQuery:
$.post(
"/download.action",{
para1:value1,
para2:value2
....
},function(data){
console.info(data);
}
);
"Firebug" programoje matau, kad duomenys gaunami naudojant dvejetainį srautą. Įdomu, kaip atidaryti failų atsisiuntimo langą, su kuriuo naudotojas galėtų išsaugoti failą vietoje?
2019 m. modernių naršyklių atnaujinimas
Šį metodą dabar rekomenduočiau su keliomis išlygomis:
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 Originalus jQuery/iframe/Cookie pagrįstas metodas
Bluish yra visiškai teisus, jūs negalite to padaryti per Ajax, nes JavaScript negali įrašyti failų tiesiogiai į vartotojo kompiuterį (dėl saugumo sumetimų). Deja, nukreipdami pagrindinio lango URL į failo atsisiuntimo adresą, galite mažai kontroliuoti naudotojo patirtį, kai failas atsisiunčiamas.
Sukūriau jQuery File Download, kuris leidžia "Ajax like" patirtį su failų atsisiuntimu, papildytą OnSuccess ir OnFailure iškvietimais, kad būtų užtikrinta geresnė vartotojo patirtis. Peržiūrėkite mano tinklaraščio įrašą apie dažniausiai pasitaikančias problemas, kurias šis įskiepis išsprendžia, ir kai kuriuos jo naudojimo būdus, taip pat jQuery File Download demonstracinę versiją. Čia yra šaltinis.
Čia pateikiama paprasta įskiepio šaltinis naudojimo demonstracinė versija, kurioje naudojamas įskiepis šaltinis su pažadais. Demo puslapyje pateikiama ir daug kitų, 'geresnio UX' pavyzdžių.
$.fileDownload('some/file.pdf')
.done(function () { alert('File download a success!'); })
.fail(function () { alert('File download failed!'); });
Priklausomai nuo to, kokias naršykles reikia palaikyti, galbūt galėsite naudoti https://github.com/eligrey/FileSaver.js/, kuris leidžia aiškiau valdyti nei IFRAME metodas, kurį naudoja jQuery File Download.
Nė vienas nepaskelbė šio @Pekka's sprendimas... todėl aš jį paskelbsiu. Jis gali kam nors padėti.
Jums nereikia to daryti per Ajax. Tiesiog naudokite
window.location="download.action?para1=value1...."
1. Framework agnostic: Servletas, parsisiunčiantis failą kaip priedą
<!-- with JS -->
<a href="javascript:window.location='downloadServlet?param1=value1'">
download
</a>
<!-- without JS -->
<a href="downloadServlet?param1=value1" >download</a>
2. Struts2 Framework: Veiksmas, kuriuo parsisiunčiamas failas kaip priedas
<!-- with JS -->
<a href="javascript:window.location='downloadAction.action?param1=value1'">
download
</a>
<!-- without JS -->
<a href="downloadAction.action?param1=value1" >download</a>
Geriau būtų naudoti <s:a>
žymą, nukreipiančią su OGNL į URL, sukurtą su <s:url>
žyma:
<!-- without JS, with Struts tags: THE RIGHT WAY -->
<s:url action="downloadAction.action" var="url">
<s:param name="param1">value1</s:param>
</s:ulr>
<s:a href="%{url}" >download</s:a>
Pirmiau nurodytais atvejais į atsakymą reikia įrašyti Content-Disposition antraštę, nurodant, kad failas turi būti atsisiųstas (priedas
), o ne atidarytas naršyklėje (inline
). Taip pat reikia nurodyti Content Type (turinio tipą) ir galbūt norėsite įrašyti failo pavadinimą ir ilgį (kad naršyklė galėtų nupiešti realią progreso juostą).
Pavyzdžiui, atsisiunčiant ZIP failą:
response.setContentType("application/zip");
response.addHeader("Content-Disposition",
"attachment; filename=\"name of my file.zip\"");
response.setHeader("Content-Length", myFile.length()); // or myByte[].length...
Naudojant "Struts2" (nebent naudojate veiksmą kaip servletą, pavyzdžiui, hack tiesioginiam srautui), jums nereikia nieko tiesiogiai įrašyti į atsakymą; pakaks naudoti srauto rezultato tipą ir sukonfigūruoti jį struts.xml: PAVYZDYS.
<result name="success" type="stream">
<param name="contentType">application/zip</param>
<param name="contentDisposition">attachment;filename="${fileName}"</param>
<param name="contentLength">${fileLength}</param>
</result>
3. Nepriklauso nuo sistemos (/ Struts2 sistema): Servlet(/Action), atidarantis failą naršyklėje
Jei norite atidaryti failą naršyklėje, užuot jį atsisiuntę, Content-disposition turi būti nustatytas į inline, tačiau taikinys negali būti dabartinio lango vieta; turite nukreipti į naują langą, sukurtą javascript, <iframe>
puslapyje, arba į naują langą, sukurtą "on-the-fly" naudojant "discussed" target="_blank":
<!-- From a parent page into an IFrame without javascript -->
<a href="downloadServlet?param1=value1" target="iFrameName">
download
</a>
<!-- In a new window without javascript -->
<a href="downloadServlet?param1=value1" target="_blank">
download
</a>
<!-- In a new window with javascript -->
<a href="javascript:window.open('downloadServlet?param1=value1');" >
download
</a>