Response.TransmitFile并在传输后删除它

9

我需要在我的网站上实现GEDCOM导出功能。

当导出为GEDCOM文件时,我的.NET代码会在服务器上创建一个文件。

然后,我需要从服务器下载该文件到客户端,并询问用户要保存该文件的位置,这意味着需要使用SaveDialog。

下载完成后,我希望从服务器中删除该文件。

我已经有了一个将文件从服务器传输到客户端的代码:

Response.ContentType = "text/xml";
Response.AppendHeader("Content-Disposition", "attachment; filename=" + FileName);
Response.TransmitFile(Server.MapPath("~/" + FileName));
Response.End();

从这个链接中得知,但是我无法在这段代码之后删除文件,因为Response.End结束了响应,所以在该行之后写的任何代码都不会执行。

如果我在Response.End()之前编写删除文件的代码,则文件不会被传输并且会出现错误。

2个回答

24

在 Response.End 后面放置的任何内容都不会被执行,因为它会抛出 ThreadAbortException 来停止页面在那一点上的执行。

请尝试使用以下方法替代:

string responseFile = Server.MapPath("~/" + FileName);

try{
    Response.ContentType = "text/xml";
    Response.AppendHeader("Content-Disposition", "attachment; filename=" + FileName);
    Response.TransmitFile(responseFile);
    Response.Flush();
}
finally {
    File.Delete(responseFile);
}

1
Response.Flush是什么,Response.End又是什么?请问它们之间有何区别? - Radhi
Response.Flush会强制输出任何缓冲的输出(如果有的话),但不会抛出ThreadAbortException - 响应仍在进行中。Response.End刷新,但然后抛出无法停止的ThreadAbortException。将删除代码放在Finally块中可确保无论结果如何都会运行。 - Josh
6
这段代码无法处理用户在文件下载对话框中点击“取消”按钮的情况。当发生这种情况时,会抛出一个HttpException异常,其中包含消息“The remote host closed the connection. The error code is 0x800703E3.”然后在finally块中,Delete操作失败并抛出一个IOException异常,消息为“The process cannot access the file 'C:\Windows\TEMP\tmp5CA3.tmp' because it is being used by another process.”我添加了一个catch(HttpException)并在其中调用Response.End()方法,这个方法对我很有效。 - Colin

2

如果文件比较小,您可以将其加载到字节数组中,以便在仍然能够发送数据的同时删除该文件:

Response.ContentType = "text/xml";
Response.AppendHeader("Content-Disposition", "attachment; filename=" + FileName);
string path = Server.MapPath("~/" + FileName);
byte[] data = File.ReadAllBytes(path);
File.Delete(path);
Response.BinaryWrite(data);
Response.End();

嗨,Response.TransmitFile 和 Response.BinaryWrite 在性能上有什么区别吗? - Radhi
@Radhi:并不完全是这样。BinaryWrite 当然更快,因为数据已经在内存中了,但是与加载数据一起使用时,它和 TransmitFile 做的事情是一样的。 - Guffa

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