hgu*_*ser 391 javascript ajax jquery jsp download
我在服务器端有一个Struts2动作用于文件下载.
<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>
Run Code Online (Sandbox Code Playgroud)
但是当我使用jQuery调用动作时:
$.post(
"/download.action",{
para1:value1,
para2:value2
....
},function(data){
console.info(data);
}
);
Run Code Online (Sandbox Code Playgroud)
在Firebug中我看到使用二进制流检索数据.我想知道如何打开用户可以在本地保存文件的文件下载窗口?
Joh*_*ner 640
蓝相是完全正确这一点,你不能做到这一点通过Ajax,因为JavaScript不能直接将文件保存到用户的计算机(出于安全考虑).不幸的是,将主窗口的 URL 指向文件下载意味着您几乎无法控制文件下载时的用户体验.
我创建了jQuery文件下载,它允许使用OnSuccess和OnFailure回调完成文件下载的"类似Ajax"体验,以提供更好的用户体验.看看我的博客文章,了解插件解决的常见问题以及使用它的一些方法,以及jQuery文件下载的演示.这是来源
这是一个使用带有promises 的插件源的简单用例演示.该演示页面还包含许多其他"更好的用户体验"示例.
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!'));
Run Code Online (Sandbox Code Playgroud)
根据您需要支持的浏览器,您可以使用https://github.com/eligrey/FileSaver.js/,它允许比jQuery文件下载使用的IFRAME方法更明确的控制.
blu*_*ish 211
没有人发布这个@Pekka的解决方案 ......所以我会发布它.它可以帮助某人.
您不需要通过Ajax执行此操作.只是用
window.location="download.action?para1=value1...."
Run Code Online (Sandbox Code Playgroud)
Luk*_*nga 34
你可以使用HTML5
注意:返回的文件数据必须是base64编码的,因为你不能JSON编码二进制数据
在我的AJAX
回复中,我有一个如下所示的数据结构:
{
result: 'OK',
download: {
mimetype: string(mimetype in the form 'major/minor'),
filename: string(the name of the file to download),
data: base64(the binary data as base64 to download)
}
}
Run Code Online (Sandbox Code Playgroud)
这意味着我可以执行以下操作以通过AJAX保存文件
var a = document.createElement('a');
if (window.URL && window.Blob && ('download' in a) && window.atob) {
// Do it the HTML5 compliant way
var blob = base64ToBlob(result.download.data, result.download.mimetype);
var url = window.URL.createObjectURL(blob);
a.href = url;
a.download = result.download.filename;
a.click();
window.URL.revokeObjectURL(url);
}
Run Code Online (Sandbox Code Playgroud)
函数base64ToBlob取自此处,必须按照此函数使用
function base64ToBlob(base64, mimetype, slicesize) {
if (!window.atob || !window.Uint8Array) {
// The current browser doesn't have the atob function. Cannot continue
return null;
}
mimetype = mimetype || '';
slicesize = slicesize || 512;
var bytechars = atob(base64);
var bytearrays = [];
for (var offset = 0; offset < bytechars.length; offset += slicesize) {
var slice = bytechars.slice(offset, offset + slicesize);
var bytenums = new Array(slice.length);
for (var i = 0; i < slice.length; i++) {
bytenums[i] = slice.charCodeAt(i);
}
var bytearray = new Uint8Array(bytenums);
bytearrays[bytearrays.length] = bytearray;
}
return new Blob(bytearrays, {type: mimetype});
};
Run Code Online (Sandbox Code Playgroud)
如果您的服务器正在转储要保存的filedata,这很好.但是,我还没有弄清楚如何实现HTML4后备
And*_*ios 26
1.框架不可知:Servlet下载文件作为附件
<!-- with JS -->
<a href="javascript:window.location='downloadServlet?param1=value1'">
download
</a>
<!-- without JS -->
<a href="downloadServlet?param1=value1" >download</a>
Run Code Online (Sandbox Code Playgroud)
2. Struts2 Framework:动作下载文件作为附件
<!-- with JS -->
<a href="javascript:window.location='downloadAction.action?param1=value1'">
download
</a>
<!-- without JS -->
<a href="downloadAction.action?param1=value1" >download</a>
Run Code Online (Sandbox Code Playgroud)
最好将<s:a>
带有OGNL的标记指向使用标记创建的URL<s:url>
:
<!-- 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>
Run Code Online (Sandbox Code Playgroud)
在上述情况下,您需要将Content-Disposition标头写入响应,指定文件需要下载(attachment
)而不是浏览器打开(inline
).您还需要指定内容类型,并且可能需要添加文件名和长度(以帮助浏览器绘制真实的进度条).
例如,下载ZIP时:
response.setContentType("application/zip");
response.addHeader("Content-Disposition",
"attachment; filename=\"name of my file.zip\"");
response.setHeader("Content-Length", myFile.length()); // or myByte[].length...
Run Code Online (Sandbox Code Playgroud)
使用Struts2(除非您使用Action作为Servlet,例如直接流式传输),您不需要直接向响应写入任何内容; 只需使用Stream结果类型并在struts.xml中配置它就可以了:例子
<result name="success" type="stream">
<param name="contentType">application/zip</param>
<param name="contentDisposition">attachment;filename="${fileName}"</param>
<param name="contentLength">${fileLength}</param>
</result>
Run Code Online (Sandbox Code Playgroud)
3.框架不可知(/ Struts2框架):Servlet(/ Action)在浏览器内打开文件
如果要在浏览器中打开文件而不是下载它,则必须将Content-disposition设置为inline,但目标不能是当前窗口位置; 你必须定位一个由javascript创建的新窗口,一个<iframe>
在页面中,或者使用"讨论"的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>
Run Code Online (Sandbox Code Playgroud)
ndp*_*dpu 23
我创建了一个小功能作为解决方案解决方案(受@JohnCulviner插件启发):
// creates iframe and form in it with hidden field,
// then submit form with provided data
// url - form url
// data - data to form field
// input_name - form hidden input name
function ajax_download(url, data, input_name) {
var $iframe,
iframe_doc,
iframe_html;
if (($iframe = $('#download_iframe')).length === 0) {
$iframe = $("<iframe id='download_iframe'" +
" style='display: none' src='about:blank'></iframe>"
).appendTo("body");
}
iframe_doc = $iframe[0].contentWindow || $iframe[0].contentDocument;
if (iframe_doc.document) {
iframe_doc = iframe_doc.document;
}
iframe_html = "<html><head></head><body><form method='POST' action='" +
url +"'>" +
"<input type=hidden name='" + input_name + "' value='" +
JSON.stringify(data) +"'/></form>" +
"</body></html>";
iframe_doc.open();
iframe_doc.write(iframe_html);
$(iframe_doc).find('form').submit();
}
Run Code Online (Sandbox Code Playgroud)
点击事件演示:
$('#someid').on('click', function() {
ajax_download('/download.action', {'para1': 1, 'para2': 2}, 'dataname');
});
Run Code Online (Sandbox Code Playgroud)
Joã*_*cos 20
使浏览器下载文件的简单方法是发出如下请求:
function downloadFile(urlToSend) {
var req = new XMLHttpRequest();
req.open("GET", urlToSend, true);
req.responseType = "blob";
req.onload = function (event) {
var blob = req.response;
var fileName = req.getResponseHeader("fileName") //if you have the fileName header available
var link=document.createElement('a');
link.href=window.URL.createObjectURL(blob);
link.download=fileName;
link.click();
};
req.send();
}
Run Code Online (Sandbox Code Playgroud)
这将打开浏览器下载弹出窗口.
Sha*_*yne 15
好吧,基于ndpu的代码下面有一个改进的(我认为)ajax_download的版本; -
function ajax_download(url, data) {
var $iframe,
iframe_doc,
iframe_html;
if (($iframe = $('#download_iframe')).length === 0) {
$iframe = $("<iframe id='download_iframe'" +
" style='display: none' src='about:blank'></iframe>"
).appendTo("body");
}
iframe_doc = $iframe[0].contentWindow || $iframe[0].contentDocument;
if (iframe_doc.document) {
iframe_doc = iframe_doc.document;
}
iframe_html = "<html><head></head><body><form method='POST' action='" +
url +"'>"
Object.keys(data).forEach(function(key){
iframe_html += "<input type='hidden' name='"+key+"' value='"+data[key]+"'>";
});
iframe_html +="</form></body></html>";
iframe_doc.open();
iframe_doc.write(iframe_html);
$(iframe_doc).find('form').submit();
}
Run Code Online (Sandbox Code Playgroud)
像这样用它; -
$('#someid').on('click', function() {
ajax_download('/download.action', {'para1': 1, 'para2': 2});
});
Run Code Online (Sandbox Code Playgroud)
params作为正确的post params发送,好像来自输入而不是像前面的例子那样作为json编码的字符串.
CAVEAT:对这些形式的可变注射潜力保持警惕.可能有一种更安全的方法来编码这些变量.或者考虑逃避它们.
Nar*_*ula 15
我遇到了同样的问题并成功解决了它.我的用例是这样的.
"将JSON数据发布到服务器并接收excel文件.该excel文件由服务器创建并作为对客户端的响应返回.在浏览器中将该响应下载为具有自定义名称的文件 "
$("#my-button").on("click", function(){
// Data to post
data = {
ids: [1, 2, 3, 4, 5]
};
// Use XMLHttpRequest instead of Jquery $ajax
xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
var a;
if (xhttp.readyState === 4 && xhttp.status === 200) {
// Trick for making downloadable link
a = document.createElement('a');
a.href = window.URL.createObjectURL(xhttp.response);
// Give filename you wish to download
a.download = "test-file.xls";
a.style.display = 'none';
document.body.appendChild(a);
a.click();
}
};
// Post data to URL which handles post request
xhttp.open("POST", excelDownloadUrl);
xhttp.setRequestHeader("Content-Type", "application/json");
// You should set responseType as blob for binary responses
xhttp.responseType = 'blob';
xhttp.send(JSON.stringify(data));
});
Run Code Online (Sandbox Code Playgroud)
上面的代码片段正在执行以下操作
在这里,我们需要在服务器端仔细设置一些东西.我在Python Django HttpResponse中设置了几个标题.如果使用其他编程语言,则需要相应地设置它们.
# In python django code
response = HttpResponse(file_content, content_type="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
Run Code Online (Sandbox Code Playgroud)
由于我在这里下载xls(excel),我将contentType调整为高于1.您需要根据文件类型进行设置.您可以使用此技术下载任何类型的文件.
M46*_*M46 14
我的方法完全基于 jQuery。对我来说,问题是它必须是 POST-HTTP 调用。我希望它能够由 jQuery 单独完成。
解决方案:
$.ajax({
type: "POST",
url: "/some/webpage",
headers: {'X-CSRF-TOKEN': csrfToken},
data: additionalDataToSend,
dataType: "text",
success: function(result) {
let blob = new Blob([result], { type: "application/octetstream" });
let a = document.createElement('a');
a.href = window.URL.createObjectURL(blob);
a.download = "test.xml";;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
window.URL.revokeObjectURL(a.href);
...
},
error: errorDialog
});
Run Code Online (Sandbox Code Playgroud)
解释:
我和其他许多人所做的就是在网页上创建一个链接,指示应该下载目标并将http请求的结果作为目标。之后,我将链接附加到文档,而不是简单地单击链接并随后删除链接。您不再需要 iframe。
神奇之处就在于线条
let blob = new Blob([result], { type: "application/octetstream" });
a.href = window.URL.createObjectURL(blob);
Run Code Online (Sandbox Code Playgroud)
有趣的是,该解决方案仅适用于“ blob ”。正如您在其他答案中看到的,有些答案只是使用 blob,但没有解释为什么以及如何创建它。正如您可以在Mozilla 开发人员文档中读到的那样,您需要一个文件、媒体资源或 blob 才能使“ createObjectURL() ”函数正常工作。问题是您的 http 响应可能不是其中任何一个。因此,您必须做的第一件事是将响应转换为 blob。这就是第一行的作用。然后,您可以将“ createObjectURL ”与新创建的 blob 一起使用。如果您单击该链接,您的浏览器将打开一个文件保存对话框,您可以保存数据。显然,您可能无法为要下载的文件定义固定的文件名。那么你必须让你的回答更加复杂,就像卢克的回答一样。
并且不要忘记释放内存,尤其是在处理大文件时。更多示例和信息可以查看JS blob 对象的详细信息
这是我做的,纯粹的javascript和HTML.没有测试它,但这应该适用于所有浏览器.
Javascript函数
var iframe = document.createElement('iframe');
iframe.id = "IFRAMEID";
iframe.style.display = 'none';
document.body.appendChild(iframe);
iframe.src = 'SERVERURL'+'?' + $.param($scope.filtro);
iframe.addEventListener("load", function () {
console.log("FILE LOAD DONE.. Download should start now");
});
Run Code Online (Sandbox Code Playgroud)
仅使用所有浏览器支持的组件,无需其他库.
这是我的服务器端JAVA Spring控制器代码.
@RequestMapping(value = "/rootto/my/xlsx", method = RequestMethod.GET)
public void downloadExcelFile(@RequestParam(value = "param1", required = false) String param1,
HttpServletRequest request, HttpServletResponse response)
throws ParseException {
Workbook wb = service.getWorkbook(param1);
if (wb != null) {
try {
String fileName = "myfile_" + sdf.format(new Date());
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setHeader("Content-disposition", "attachment; filename=\"" + fileName + ".xlsx\"");
wb.write(response.getOutputStream());
response.getOutputStream().close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Run Code Online (Sandbox Code Playgroud)
小智 6
HTML 代码:
<button type="button" id="GetFile">Get File!</button>
Run Code Online (Sandbox Code Playgroud)
jQuery 代码:
$('#GetFile').on('click', function () {
$.ajax({
url: 'https://s3-us-west-2.amazonaws.com/s.cdpn.io/172905/test.pdf',
method: 'GET',
xhrFields: {
responseType: 'blob'
},
success: function (data) {
var a = document.createElement('a');
var url = window.URL.createObjectURL(data);
a.href = url;
a.download = 'myfile.pdf';
document.body.append(a);
a.click();
a.remove();
window.URL.revokeObjectURL(url);
}
});
});
Run Code Online (Sandbox Code Playgroud)
小智 6
AJAX接收文件后如何下载文件
文件创建时间长,需要显示PRELOADER的时候很方便
提交 Web 表单时的示例:
<script>
$(function () {
$('form').submit(function () {
$('#loader').show();
$.ajax({
url: $(this).attr('action'),
data: $(this).serialize(),
dataType: 'binary',
xhrFields: {
'responseType': 'blob'
},
success: function(data, status, xhr) {
$('#loader').hide();
// if(data.type.indexOf('text/html') != -1){//If instead of a file you get an error page
// var reader = new FileReader();
// reader.readAsText(data);
// reader.onload = function() {alert(reader.result);};
// return;
// }
var link = document.createElement('a'),
filename = 'file.xlsx';
// if(xhr.getResponseHeader('Content-Disposition')){//filename
// filename = xhr.getResponseHeader('Content-Disposition');
// filename=filename.match(/filename="(.*?)"/)[1];
// filename=decodeURIComponent(escape(filename));
// }
link.href = URL.createObjectURL(data);
link.download = filename;
link.click();
}
});
return false;
});
});
</script>
Run Code Online (Sandbox Code Playgroud)
可选的函数被注释掉以简化示例。
无需在服务器上创建临时文件。
在 jQuery v2.2.4 上OK。旧版本会报错:
Uncaught DOMException: Failed to read the 'responseText' property from 'XMLHttpRequest': The value is only accessible if the object's 'responseType' is '' or 'text' (was 'blob').
Run Code Online (Sandbox Code Playgroud)
function downloadURI(uri, name)
{
var link = document.createElement("a");
link.download = name;
link.href = uri;
link.click();
}
Run Code Online (Sandbox Code Playgroud)
我尝试下载一个 CSV 文件,然后在下载完成后做一些事情。所以我需要实现一个适当的callback
功能。
使用window.location="..."
不是一个好主意,因为我下载完成后无法运行程序。像这样的东西,改变标题所以这不是一个好主意。
fetch
是一个不错的选择,但它不能支持 IE 11。并且window.URL.createObjectURL
不能支持 IE 11。你可以参考这个。
这是我的代码,它类似于 Shahrukh Alam 的代码。但是您应该注意window.URL.createObjectURL
可能会造成内存泄漏。你可以参考这个。当响应到达时,数据将存储到浏览器的内存中。因此,在您单击a
链接之前,文件已下载。这意味着您可以在下载后做任何事情。
$.ajax({
url: 'your download url',
type: 'GET',
}).done(function (data, textStatus, request) {
// csv => Blob
var blob = new Blob([data]);
// the file name from server.
var fileName = request.getResponseHeader('fileName');
if (window.navigator && window.navigator.msSaveOrOpenBlob) { // for IE
window.navigator.msSaveOrOpenBlob(blob, fileName);
} else { // for others
var url = window.URL.createObjectURL(blob);
const a = document.createElement('a');
a.style.display = 'none';
a.href = url;
a.download = fileName;
document.body.appendChild(a);
a.click();
window.URL.revokeObjectURL(url);
//Do something after download
...
}
}).then(after_download)
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
684565 次 |
最近记录: |