Javascript 通过jQuery.Ajax下载一个文件
我在服务器端有一个Struts2操作用于文件下载Javascript 通过jQuery.Ajax下载一个文件,javascript,jquery,ajax,jsp,download,Javascript,Jquery,Ajax,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</
<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>
在Firebug中,我看到数据是用二进制流检索的。我想知道如何打开文件下载窗口,用户可以用它在本地保存文件?Noone发布了这个。。。所以我会把它贴出来。它可以帮助某人
您不需要通过Ajax来实现这一点。只用
window.location="download.action?para1=value1...."
2019现代浏览器更新
这是我现在推荐的方法,但有几个注意事项:
需要一个相对现代的浏览器
如果预期文件非常大,您可能应该执行类似于原始方法iframe和cookie的操作,因为下面的一些操作可能会消耗至少与正在下载的文件一样大的系统内存和/或其他有趣的CPU副作用。
取回https://jsonplaceholder.typicode.com/todos/1'
.thenresp=>resp.blob
.thenblob=>{
const url=window.url.createObjectURLblob;
const a=document.createElement'a';
a、 style.display='none';
a、 href=url;
//您想要的文件名
a、 下载='todo-1.json';
document.body.a;
a、 点击;
window.URL.revokeObjectURLurl;
警告“您的文件已下载!”;//或者您知道,有更好的用户体验。。。
}
.catch=>提醒“哦,不!” 一,。框架不可知:Servlet将文件作为附件下载
使用Struts2,除非您将操作用作Servlet,例如,一种黑客攻击,否则您不需要直接向响应写入任何内容;只需使用并在struts.xml中配置即可:
三,。框架不可知/Struts2框架:浏览器中的Servlet/Action打开文件
如果要在浏览器中打开文件,而不是下载文件,则必须将内容配置设置为“内联”,但目标不能是当前窗口位置;您必须以javascript创建的新窗口、页面中的或动态创建的新窗口为目标,所讨论的目标=\u 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>
受@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();
}
好的,基于ndpu的代码,这里有一个改进版的ajax\u下载-
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();
}
参数作为正确的post参数发送,就像来自输入一样,而不是像前面的示例那样作为json编码的字符串
警告:小心那些表单上可能存在的变量注入。可能有一种更安全的方法来编码这些变量。或者考虑转义它们。好的,下面是使用MVC时的工作代码,您可以从控制器获取文件 假设您有字节数组声明和填充,您只需要使用System.Web.Mvc使用File函数
byte[] bytes = .... insert your bytes in the array
return File(bytes, System.Net.Mime.MediaTypeNames.Application.Octet, "nameoffile.exe");
然后,在同一控制器中,添加这两个函数
protected override void OnResultExecuting(ResultExecutingContext context)
{
CheckAndHandleFileResult(context);
base.OnResultExecuting(context);
}
private const string FILE_DOWNLOAD_COOKIE_NAME = "fileDownload";
/// <summary>
/// If the current response is a FileResult (an MVC base class for files) then write a
/// cookie to inform jquery.fileDownload that a successful file download has occured
/// </summary>
/// <param name="context"></param>
private void CheckAndHandleFileResult(ResultExecutingContext context)
{
if (context.Result is FileResult)
//jquery.fileDownload uses this cookie to determine that a file download has completed successfully
Response.SetCookie(new HttpCookie(FILE_DOWNLOAD_COOKIE_NAME, "true") { Path = "/" });
else
//ensure that the cookie is removed in case someone did a file download without using jquery.fileDownload
if (Request.Cookies[FILE_DOWNLOAD_COOKIE_NAME] != null)
Response.Cookies[FILE_DOWNLOAD_COOKIE_NAME].Expires = DateTime.Now.AddYears(-1);
}
你可以使用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)
}
}
res.set('Content-Disposition', 'attachment; filename=file.txt');
这意味着我可以通过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);
}
函数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});
};
如果您的服务器正在转储要保存的文件数据,这是很好的。然而,我还没有完全弄清楚如何实现HTML4回退如果您想使用jQuery文件下载,请注意IE。 您需要重置响应,否则将无法下载
//The IE will only work if you reset response
getServletResponse().reset();
//The jquery.fileDownload needs a cookie be set
getServletResponse().setHeader("Set-Cookie", "fileDownload=true; path=/");
//Do the reset of your action create InputStream and return
您的操作可以实现ServletResponseAware来访问getServletResponse在上述答案中添加更多内容以下载文件 下面是一些生成字节数组的JavaSpring代码
@RequestMapping(value = "/downloadReport", method = { RequestMethod.POST })
public ResponseEntity<byte[]> downloadReport(
@RequestBody final SomeObejct obj, HttpServletResponse response) throws Exception {
OutputStream out = new ByteArrayOutputStream();
// write something to output stream
HttpHeaders respHeaders = new HttpHeaders();
respHeaders.setContentType(MediaType.APPLICATION_OCTET_STREAM);
respHeaders.add("X-File-Name", name);
ByteArrayOutputStream bos = (ByteArrayOutputStream) out;
return new ResponseEntity<byte[]>(bos.toByteArray(), respHeaders, HttpStatus.CREATED);
}
上面将下载文件这里是我做的,纯javascript和html。没有测试它,但这应该适用于所有浏览器 Javascript函数 只使用所有浏览器支持的组件,无需额外的 图书馆 这是我的服务器端JavaSpring控制器代码
我面对同样的问题,并成功地解决了它。我的用例是这样的 将JSON数据发布到服务器并接收excel文件。 该excel文件由服务器创建,并作为响应返回给客户端。在浏览器中将该响应下载为具有自定义名称的文件 上面的代码片段只是做了以下工作 使用XMLHttpRequest将数组作为JSON发布到服务器。
在以blobbinary形式获取内容之后,我们将创建一个可下载的URL,并将其附加到一个不可见的链接上,然后单击它。我在这里发了一个帖子。相反,你也可以做一个简单的尝试。我们不能通过Ajax下载该文件,必须使用XMLHttpRequest。 在这里,我们需要仔细地在服务器端设置一些东西。我在Python Django HttpResponse中设置了几个标题。如果使用其他编程语言,则需要相应地设置它们
# In python django code
response = HttpResponse(file_content, content_type="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
因为我在这里下载了xlsexcel,所以我将contentType调整为上面的一个。您需要根据您的文件类型进行设置。你可以使用这项技术
nique可下载任何类型的文件。让浏览器下载文件的简单方法是发出如下请求:
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();
}
这将打开浏览器下载弹出窗口。在Rails中,我是这样做的:
function download_file(file_id) {
let url = '/files/' + file_id + '/download_file';
$.ajax({
type: 'GET',
url: url,
processData: false,
success: function (data) {
window.location = url;
},
error: function (xhr) {
console.log(' Error: >>>> ' + JSON.stringify(xhr));
}
});
}
诀窍是window.location部分。控制器的方法如下所示:
# GET /files/{:id}/download_file/
def download_file
send_file(@file.file,
:disposition => 'attachment',
:url_based_filename => false)
end
我发现了一个修复方法,虽然它实际上没有使用ajax,但它允许您使用javascript调用请求下载,然后在下载实际开始时获得回调。我发现,如果链接运行服务器端脚本,在发送文件之前编写文件需要一点时间,那么这将非常有用。因此,您可以提醒他们它正在处理,然后当它最终发送文件时,删除该处理通知。这就是为什么我想首先尝试通过ajax加载文件,以便在请求文件时发生一个事件,在实际开始下载时发生另一个事件
<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>
在头版的js
function expdone()
{
document.getElementById('exportdiv').style.display='none';
}
function expgo()
{
document.getElementById('exportdiv').style.display='block';
document.getElementById('exportif').src='test2.php?arguments=data';
}
iframe
<div id="exportdiv" style="display:none;">
<img src="loader.gif"><br><h1>Generating Report</h1>
<iframe id="exportif" src="" style="width: 1px;height: 1px; border:0px;"></iframe>
</div>
然后是另一个文件:
<!DOCTYPE html>
<html>
<head>
<script>
function expdone()
{
window.parent.expdone();
}
</script>
</head>
<body>
<iframe id="exportif" src="<?php echo "http://10.192.37.211/npdtracker/exportthismonth.php?arguments=".$_GET["arguments"]; ?>"></iframe>
<script>document.getElementById('exportif').onload= expdone;</script>
</body></html>
我认为有一种方法可以使用js读取get数据,这样就不需要php了。但我现在还不知道,而且我使用的服务器支持php,所以这对我来说是可行的。我想我会分享它,以防它对任何人都有帮助。可以肯定的是,您不能通过Ajax调用来实现它 然而,有一个解决办法 步骤: 如果您使用form.submit下载文件,您可以执行以下操作: 创建从客户端到服务器的ajax调用,并将文件流存储在会话中。 从服务器返回成功后,调用form.submit以流式传输存储在会话中的文件流。
如果您想在制作form.submit后决定是否需要下载文件,这将非常有用,例如:在form.submit上,服务器端会发生异常,您可能需要在客户端显示自定义消息,而不是崩溃,在这种情况下,此实现可能会有所帮助。我为这个问题挣扎了很长时间。最后,一个优雅的外部库帮助了我。使用window.open 例如,您可以将这行代码放入单击处理程序中:
window.open('/file.txt', '_blank');
由于窗口名为“\u blank”,它将打开一个新选项卡,该选项卡将打开URL
您的服务器端代码也应该具有如下内容:
{
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)
}
}
res.set('Content-Disposition', 'attachment; filename=file.txt');
这样,浏览器应该提示用户将文件保存到磁盘,而不是仅仅向他们显示文件。它还将自动关闭刚刚打开的选项卡。还有另一种解决方案可以在ajax中下载网页。但我指的是一个必须先处理然后下载的页面 首先,您需要将页面处理与结果下载分开 1在ajax调用中只进行页面计算 $.post("CalculusPage.php", { calculusFunction: true, ID: 29, data1: "a", data2: "b" }, function(data, status) { if (status == "success") { /* 2) In the answer the page that uses the previous calculations is downloaded. For example, this can be a page that prints the results of a table calculated in the ajax call. */ window.location.href = DownloadPage.php+"?ID="+29; } } ); // For example: in the CalculusPage.php if ( !empty($_POST["calculusFunction"]) ) { $ID = $_POST["ID"]; $query = "INSERT INTO ExamplePage (data1, data2) VALUES ('".$_POST["data1"]."', '".$_POST["data2"]."') WHERE id = ".$ID; ... } // For example: in the DownloadPage.php $ID = $_GET["ID"]; $sede = "SELECT * FROM ExamplePage WHERE id = ".$ID; ... $filename="Export_Data.xls"; header("Content-Type: application/vnd.ms-excel"); header("Content-Disposition: inline; filename=$filename"); ...
我希望这个解决方案能像对我一样对很多人有用。我尝试下载一个CSV文件,然后在下载完成后做一些事情。所以我需要实现一个适当的回调函数
The HTML Code:-
'<button type="button" id="GetFile">Get File!</button>'
The jQuery Code:-
'$('#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);
}
});
});'
正在使用window.location=。。。这不是一个好主意,因为我完成下载后无法操作程序。像这样,改变标题,这样不是一个好主意
不过,fetch是一个不错的选择。和window.URL.createObjectURL无法支持IE 11。您可以参考
这是我的代码,类似于沙鲁克阿拉姆的代码。但是您应该注意window.URL.createObjectURL可能会造成内存泄漏。你可以参考。当响应到达时,数据将存储到浏览器的内存中。因此,在单击链接之前,文件已下载。这意味着你可以在下载后做任何事情
$.ajax{
url:“您的下载url”,
键入:“GET”,
}.done函数数据、文本状态、请求{
//csv=>Blob
var blob=新blob[数据];
//来自服务器的文件名。
var fileName=request.getResponseHeader'fileName';
如果window.navigator&&window.navigator.msSaveOrOpenBlob{//for IE
window.navigator.msSaveOrOpenBlobblob,文件名;
}其他{//
var url=window.url.createObjectURLblob;
const a=document.createElement'a';
a、 style.display='none';
a、 href=url;
a、 下载=文件名;
document.body.a;
a、 点击;
window.URL.revokeObjectURLurl;
//下载后做些什么
...
}
}。然后下载
}
通过AJAX接收文件后如何下载文件
当文件创建了很长一段时间并且需要显示预加载程序时,这会很方便
提交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>
就是这样,它在我使用asp.net core的任何浏览器中都运行得非常好 下载功能{ const api='@Url.Actionmyaction,mycontroller'; var form=new FormDatadocument.getElementById'form1'; fetchapi,{body:form,method:POST} .thenresp=>resp.blob .thenblob=>{ const url=window.url.createObjectURLblob; $'linkdownload'.attr'download','Attachement.zip'; $'linkdownload'.attr href,url; $‘链接下载’ .fadeIn3000, 函数{}; } .catch=>警报“发生错误”; } 单击以处理文件
如果服务器正在将文件写回响应中,包括cookies,如果 您可以使用它们来确定文件下载是否已开始,只需使用以下值创建一个表单并提交:
function ajaxPostDownload(url, data) {
var $form;
if (($form = $('#download_form')).length === 0) {
$form = $("<form id='download_form'" + " style='display: none; width: 1px; height: 1px; position: absolute; top: -10000px' method='POST' action='" + url + "'></form>");
$form.appendTo("body");
}
//Clear the form fields
$form.html("");
//Create new form fields
Object.keys(data).forEach(function (key) {
$form.append("<input type='hidden' name='" + key + "' value='" + data[key] + "'>");
});
//Submit the form post
$form.submit();
}
控制器方法:
[HttpPost]
public FileResult ExportFile(string DownloadToken, string Name, string Type)
{
//Set DownloadToken Cookie.
Response.SetCookie(new HttpCookie("downloadToken", DownloadToken)
{
Expires = DateTime.UtcNow.AddDays(1),
Secure = false
});
using (var output = new MemoryStream())
{
//get File
return File(output.ToArray(), "application/vnd.ms-excel", "NewFile.xls");
}
}
我的方法完全基于jQuery。我的问题是,它必须是一个后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.removeObjectURL(a.href);
...
},
error: errorDialog
});
说明:
我和其他许多人所做的是在网页上创建一个链接,指示应该下载目标并将http请求的结果作为目标。之后,我将链接附加到文档中,而不是简单地单击链接,然后删除链接。你不再需要iframe了
魔术在于台词
let blob = new Blob([result], { type: "application/octetstream" });
a.href = window.URL.createObjectURL(blob);
有趣的是,此解决方案仅适用于blob。正如您在其他答案中所看到的,有些只是使用blob,但没有解释为什么以及如何创建它。
如您所知,例如,在中,您需要一个文件、媒体资源或blob,以便函数createObjectURL正常工作。问题是您的http响应可能不是这些响应中的任何一个。
因此,您必须做的第一件事是将响应转换为blob。这是第一行所做的。然后可以将createObjectURL与新创建的blob一起使用。
如果单击链接,浏览器将打开文件保存对话框,您可以保存数据。显然,您可能无法为要下载的文件定义固定的文件名。然后你必须让你的回答更复杂,就像卢克的回答一样
不要忘记释放内存,尤其是在处理大文件时。有关更多示例和信息,您可以查看可能的重复,尽管平台不同,但我将其标记为重复,因为据我所知,解决方案是相同的,您不能也不需要通过Ajax执行此操作。因此,如果没有Ajax,只需使用window.location=download.action?para1=value1….?我喜欢您构建的内容,但我怀疑为了获得更多的StackOverFlow积分,您在这里的回答应该包含更多的细节。特别是关于你是如何解决这个问题的。如果你能确切地提到这个插件是如何绕过限制的,而不是强迫我们去你的博客/插件源代码查看它,那就太好了。例如,它是否改为发布到iframe?是否需要远程脚本来保存文件并返回url?@asgerhall当然可以,但如果所述链接消失,这完全没有用。我同意,博客是一个更好的地方,可以详细描述如何使用插件及其工作原理。但是你至少可以简单地概述一下这个插件是如何解决这个问题的。例如,通过让服务器设置一个cookie并让javascript持续查找cookie直到它存在,这就解决了问题。一旦它存在,我们可以假设下载已经完成。有了这样的信息,你可以很快地推出自己的解决方案,答案不再100%依赖于你的博客/插件/jquery,也可以应用于其他库。Royi,据我所知,AJAX永远不支持文件下载,从而导致文件下载弹出窗口保存到磁盘。你找到了一种我不知道的方法了吗?很好的一种…因为我一直在努力处理下载文件提示并使用jquery ajax..而这个解决方案对我来说非常适合..+1请注意,这要求服务器将内容处置头值设置为“附件”,否则,浏览器将重定向到并显示响应内容,或者使用window.open、“u blank”;确保无论内容处置标头如何,下载都不会替换当前浏览器内容。此解决方案的问题在于,如果操作失败/服务器返回错误,您的页面将重定向到错误页面。为了解决这个问题,使用iFrame解决方案这个解决方案的真正问题是关于POST请求。它以一种非常奇怪的方式将数据发送到服务器。我想知道是否可以修改它来创建符合要求的帖子?这是一个有效的例子。谢谢不使用iframe但不使用window.location是否可以实现这一点?我想您可以将隐藏的表单附加到DOM的底部。同样值得探索的是阴影dom的使用,尽管这在旧浏览器上不一定得到很好的支持。未捕获的安全性错误:阻止了具有原点的帧http://foo.bar.com 从访问原点为null的帧开始。请求访问的帧具有http协议,被访问的帧具有数据协议。协议必须匹配。如何将此表单映射到某个模型类?我有:@ResourceMapping public void downloadFilefinal ResourceRequest请求,final
ResourceResponse响应,@modelAttributeDownformFormModel模型,但它不工作..void:这可能是某种跨源安全问题。这可能是一个完整的堆栈溢出问题@bartex9:这在很大程度上取决于您使用的框架类型。但是,原则是采用名称和路径并存储,同时将文件本身推入文件系统的web可访问区域,或类似amazon S3的高可用性,先生,您的输入:Content Disposition,inline;。。。。保存了可怜的程序员日:这是唯一提到窗口的答案。打开其中一条评论会提到它。如果有很多参数,它就不起作用,因为你会得到太长的url错误。似乎没有为内容处置附件内容调用加载事件,因为iframe中没有加载任何内容,如果它对你有效,你可以得到console.log,请发布一个示例。这里有一个快速的提琴,一旦pdf文件加载到iframe中,就会触发加载事件ass。。此小提琴不下载,因为下载的键位于服务器端响应中。setHeaderContent-disposition,附件;文件名=\+文件名+.xlsx\;是的,在这种情况下它可以工作,但是如果文件被下载,即服务器发送内容处置:附件,那么加载事件将不会触发这是我的观点你完全正确加载事件将在服务器完成处理后立即触发并开始发送文件。这就是我要找的,1-阻止按钮并显示处理过程,这样用户就可以得到正在发生的事情的反馈。2-然后,当服务器完成处理并即将发送文件时,3-在我解锁按钮并移除处理微调器的地方触发加载事件4-用户现在弹出保存文件或浏览器开始在定义的下载位置下载文件。对不起,我的英语不好。你能解释一下你的答案吗?这将有助于其他人了解您所做的事情,以便他们能够将您的技术应用于他们的情况。只是一个警告:Safari和IE不支持下载属性,因此您的文件将以名称未知而告终。谢谢,我使用了此解决方案。工作得很有魅力。此外,如果您没有从响应中获得blob,只需创建一个新blob。如果您使用IE11a,IE处理@startsWith\R链接的更好版本确实会有所帮助。单击在firefox中似乎不起作用。。。有什么想法吗?在某些浏览器中,您可能需要将a添加到dom中,以使此代码正常工作和/或删除revokeObjectURL部分:document.body.appendChildasaved my day,也可能是一份工作:无论如何,都不是javascript专家。。。更多的java家伙。然而,我不知道为什么一个简单的CreateObjectUrlNewBlob[atobbase64]不起作用!事实并非如此,而所有的本能都说它必须这样做。grrr…在var bytechars=atobbase64行,它抛出一个错误JavaScript运行时错误:InvalidCharacterError。我使用的是Chrome版本75.0.3770.142,但我不知道这里出了什么问题。快速提问,这不会生成两次文件吗?发送ajax请求后。然后将页面重定向到相同的URL。我们怎样才能消除它?我的情况不是这样。不过我只在Chrome上测试了它。正如coderhs已经正确声明的那样,该操作会被调用两次。我也会被调用两次。我们无法通过Ajax下载该文件,必须使用XMLHttpRequest。XMLHttpRequest的定义是AJAX。对于现代web浏览器来说,这是一个非常好的解决方案。对于不支持htmlanchorement.download的IE,我正在考虑将其与专有方法相结合。仅代码的答案应该至少有一个详细的描述,解释代码如何工作以及它回答问题的原因。它提供了->VM2821:81未捕获类型错误:未能对“URL”执行“createObjectURL”:重载解析未能从内容处置中获取文件名,这个匹配对我很有用:filename.match/filename=.*/[1],不带双引号或问号-。然而,您的解决方案是经过大量搜索后唯一有效的解决方案。
<div id="exportdiv" style="display:none;">
<img src="loader.gif"><br><h1>Generating Report</h1>
<iframe id="exportif" src="" style="width: 1px;height: 1px; border:0px;"></iframe>
</div>
<!DOCTYPE html>
<html>
<head>
<script>
function expdone()
{
window.parent.expdone();
}
</script>
</head>
<body>
<iframe id="exportif" src="<?php echo "http://10.192.37.211/npdtracker/exportthismonth.php?arguments=".$_GET["arguments"]; ?>"></iframe>
<script>document.getElementById('exportif').onload= expdone;</script>
</body></html>
window.open('/file.txt', '_blank');
res.set('Content-Disposition', 'attachment; filename=file.txt');
$.post("CalculusPage.php", { calculusFunction: true, ID: 29, data1: "a", data2: "b" },
function(data, status)
{
if (status == "success")
{
/* 2) In the answer the page that uses the previous calculations is downloaded. For example, this can be a page that prints the results of a table calculated in the ajax call. */
window.location.href = DownloadPage.php+"?ID="+29;
}
}
);
// For example: in the CalculusPage.php
if ( !empty($_POST["calculusFunction"]) )
{
$ID = $_POST["ID"];
$query = "INSERT INTO ExamplePage (data1, data2) VALUES ('".$_POST["data1"]."', '".$_POST["data2"]."') WHERE id = ".$ID;
...
}
// For example: in the DownloadPage.php
$ID = $_GET["ID"];
$sede = "SELECT * FROM ExamplePage WHERE id = ".$ID;
...
$filename="Export_Data.xls";
header("Content-Type: application/vnd.ms-excel");
header("Content-Disposition: inline; filename=$filename");
...
The HTML Code:-
'<button type="button" id="GetFile">Get File!</button>'
The jQuery Code:-
'$('#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);
}
});
});'
<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>
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').
function ajaxPostDownload(url, data) {
var $form;
if (($form = $('#download_form')).length === 0) {
$form = $("<form id='download_form'" + " style='display: none; width: 1px; height: 1px; position: absolute; top: -10000px' method='POST' action='" + url + "'></form>");
$form.appendTo("body");
}
//Clear the form fields
$form.html("");
//Create new form fields
Object.keys(data).forEach(function (key) {
$form.append("<input type='hidden' name='" + key + "' value='" + data[key] + "'>");
});
//Submit the form post
$form.submit();
}
ajaxPostDownload('/fileController/ExportFile', {
DownloadToken: 'newDownloadToken',
Name: $txtName.val(),
Type: $txtType.val()
});
[HttpPost]
public FileResult ExportFile(string DownloadToken, string Name, string Type)
{
//Set DownloadToken Cookie.
Response.SetCookie(new HttpCookie("downloadToken", DownloadToken)
{
Expires = DateTime.UtcNow.AddDays(1),
Secure = false
});
using (var output = new MemoryStream())
{
//get File
return File(output.ToArray(), "application/vnd.ms-excel", "NewFile.xls");
}
}
$.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.removeObjectURL(a.href);
...
},
error: errorDialog
});
let blob = new Blob([result], { type: "application/octetstream" });
a.href = window.URL.createObjectURL(blob);