如何在ASP.NET AJAX中实现文件下载

8
我想使用标准的ASP.NET文件下载响应,就像在其他Stack Overflow问题中所述。
Response.ContentType = "application/octet-stream";
Response.AppendHeader("Content-Disposition","attachment; filename=logfile.txt");
Response.TransmitFile( Server.MapPath("~/logfile.txt") );
Response.End();

但在更新面板内部它不起作用。我该怎么做,才能在更新面板内触发下载事件并获取文件?


我很好奇为什么你不直接构建一个URL,指向你想要提供给客户端的文件,并将其提供给浏览器用于下载你的文件。 - 7wp
这是一个txt文件,通常可以直接在浏览器中显示。如果内容类型设置为“application/octet-stream”,我猜测浏览器会启动下载到磁盘而不是直接显示。 - awe
好的,“txt”文件只是一个例子。它不会直接在浏览器中显示,而是始终可下载。 - Peter Stegnar
4个回答

10

2

您需要在一个不使用Ajax的单独aspx页面中完成这个操作。Ajax是在客户端更新现有的HTML标记。您在这里尝试的是在服务器端发送任何内容到客户端之前替换响应内容。

您可以尝试以下操作:

创建一个名为Download.aspx的页面,其中包含您已经拥有的传输代码。

在您的原始页面中,您可以使用JavaScript调用下载页面,如下所示:

window.location.replace('Download.aspx');

0

您可以尝试为此工作创建一个处理程序。如果您能够修改得很好,那么它将更加安全。 对于这项工作,您需要在放置文件链接的页面中加密文件路径。

<a href=\"Downloads.ashx?f={0}\" target=\"_blank\">Your link to file</a> 
//{0} -> Encrypted file path
//target = _blank force browser to download file in another window

这里有很多加密技术(点击此处)

在您的Handler页面中,您需要将文件路径解密为原始路径,以便可以使用System.IO库读取它。

context.Response.ContentType = ""; //-->MimeType for your file's extension

如果您的MIME类型是静态图像以外的其他类型,您可以通过注册表指定它。

string mimeType = Registry.GetValue(string.Format(@"HKEY_CLASSES_ROOT\.{0}",
                  Path.GetExtension(decryptedfilePath)), "Content Type", null).ToString();

//Then everything is ready for download

byte[] buffer = File.ReadAllBytes(decryptedfilePath);
context.Response.OutputStream.Write(buffer, 0 , buffer.Length);
context.Response.Flush();

祝你好运。


0

我通过调用一个JavaScript函数来解决这个问题,该函数使用没有__EVENTTARGET的__doPostBack。

 function GxGridView_Export(exportLink, exportType) {
     var containingGrid = $(exportLink).closest("table .GxGridViewWithSlider");
     __doPostBack('', containingGrid.attr('id') + "###" + exportType);
 }

服务器端的网格然后解析 __EVENTARGUMENT 并呈现导出文件。
var eventArg = Page.Request.Form["__EVENTARGUMENT"];
if (!string.IsNullOrEmpty(eventArg) && eventArg.Contains("###"))
{
    var eventParams = eventArg.Split(new string[] { "###" }, StringSplitOptions.RemoveEmptyEntries);
    if (eventParams.Length == 2 && eventParams[0] == this.ClientID)
    {
        ExportGrid(eventParams[1]);
        return;
    }
}

我最初尝试将网格ID作为事件目标传递,但是doPostBack在某种程度上足够聪明,知道它是ajax面板内的一个控件,并执行ajax回发。 - Dale K

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接