Sunucu tarafında dosya indirmek için bir Struts2 eylemim var.
<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>
Ancak eylemi jQuery kullanarak çağırdığımda:
$.post(
"/download.action",{
para1:value1,
para2:value2
....
},function(data){
console.info(data);
}
);
Firebug'da verilerin Binary stream ile alındığını görüyorum. Acaba kullanıcının dosyayı yerel olarak kaydedebileceği dosya indirme penceresi nasıl açılır?
2019 modern tarayıcı güncellemesi
Birkaç uyarıyla birlikte şimdi önereceğim yaklaşım budur:
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 Orijinal jQuery/iframe/Cookie tabanlı yaklaşım
Bluish bu konuda tamamen haklı, bunu Ajax aracılığıyla yapamazsınız çünkü JavaScript dosyaları doğrudan bir kullanıcının bilgisayarına kaydedemez (güvenlik endişeleri nedeniyle). Ne yazık ki ana pencerenin URL'sini dosya indirmeye yönlendirmek, bir dosya indirme gerçekleştiğinde kullanıcı deneyiminin ne olacağı üzerinde çok az kontrolünüz olduğu anlamına gelir.
Daha iyi bir kullanıcı deneyimi sağlamak için OnSuccess ve OnFailure geri aramalarıyla tamamlanan dosya indirmeleriyle "Ajax benzeri" bir deneyim sağlayan jQuery File Download'yi oluşturdum. Eklentinin çözdüğü genel sorun ve onu kullanmanın bazı yolları hakkındaki blog yazıma ve ayrıca jQuery File Download'un iş başındaki demosuna bir göz atın. İşte kaynak
İşte eklentiyi kaynak vaatlerle kullanan basit bir kullanım örneği demosu. Demo sayfası]7 başka birçok 'daha iyi UX' örneği de içerir.
$.fileDownload('some/file.pdf')
.done(function () { alert('File download a success!'); })
.fail(function () { alert('File download failed!'); });
Hangi tarayıcıları desteklemeniz gerektiğine bağlı olarak, jQuery File Download'un kullandığı IFRAME yönteminden daha açık kontrol sağlayan https://github.com/eligrey/FileSaver.js/ adresini kullanabilirsiniz.
Kimse bunu @Pekka'nın çözümünü yayınlamadı... bu yüzden ben yayınlayacağım. Birilerine yardımcı olabilir.
Bunu Ajax aracılığıyla yapmanıza gerek yoktur. Sadece kullanın
window.location="download.action?para1=value1...."
1. Framework agnostik: Servlet dosyayı ek olarak indiriyor
<!-- with JS -->
<a href="javascript:window.location='downloadServlet?param1=value1'">
download
</a>
<!-- without JS -->
<a href="downloadServlet?param1=value1" >download</a>
2. Struts2 Çerçevesi: Eylem dosyayı ek olarak indiriyor
<!-- with JS -->
<a href="javascript:window.location='downloadAction.action?param1=value1'">
download
</a>
<!-- without JS -->
<a href="downloadAction.action?param1=value1" >download</a>
lt;s:url>etiketi ile oluşturulan bir *URL*'ye *OGNL* ile işaret eden
<!-- 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>
Yukarıdaki durumlarda, Content-Disposition başlığını response'a yazarak dosyanın indirilmesi gerektiğini (attachment
) ve tarayıcı tarafından açılmaması gerektiğini (inline
) belirtmeniz gerekir. İçerik Türünü* de belirtmeniz gerekir ve dosya adını ve uzunluğunu eklemek isteyebilirsiniz (tarayıcının gerçekçi bir ilerleme çubuğu çizmesine yardımcı olmak için).
Örneğin, bir ZIP indirirken:
response.setContentType("application/zip");
response.addHeader("Content-Disposition",
"attachment; filename=\"name of my file.zip\"");
response.setHeader("Content-Length", myFile.length()); // or myByte[].length...
Struts2 ile (Eylemi bir Servlet olarak kullanmıyorsanız, örneğin doğrudan akış için bir hack), yanıta doğrudan bir şey yazmanıza gerek yoktur; sadece Stream sonuç türü kullanmak ve struts.xml'de yapılandırmak işe yarayacaktır: ÖRNEK
<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. Çerçeve agnostik (/ Struts2 çerçevesi): Servlet(/Action) tarayıcı içinde dosya açma
Dosyayı indirmek yerine tarayıcı içinde açmak istiyorsanız, Content-disposition inline olarak ayarlanmalıdır, ancak hedef mevcut pencere konumu olamaz; javascript tarafından oluşturulan yeni bir pencereyi, sayfadaki bir <iframe>
yi veya "discussed" target="_blank" ile anında oluşturulan yeni bir pencereyi hedeflemelisiniz:
<!-- 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>