我的问题与this post类似,但我必须使用IIS,ASP.NET和C#执行相同的操作。如何检测Web客户端成功接收文件?
如果数据发送与否,HttpResponse
类中的任何方法都不提供反馈,TransmitFile()
只是完成其工作(不),并且不提供任何方法来知道结果。
我正在考虑使用.Filter
属性,但再次,该过滤器是基于HttpResponseStream
,它也没有提供任何反馈。
任何想法?
我的问题与this post类似,但我必须使用IIS,ASP.NET和C#执行相同的操作。如何检测Web客户端成功接收文件?
如果数据发送与否,HttpResponse
类中的任何方法都不提供反馈,TransmitFile()
只是完成其工作(不),并且不提供任何方法来知道结果。
我正在考虑使用.Filter
属性,但再次,该过滤器是基于HttpResponseStream
,它也没有提供任何反馈。
任何想法?
在致电TransmitFile
后检查Response.IsClientConnected
。
不,没有任何“作家”函数会抛出异常。知道客户端是否仍在监听的唯一方法是使用Response.IsClientConnected,如下所述。 – 2010-02-18 12:40:57
经过一番测试,我想出了以下解决方案。 TransmitFile()有一个严重的限制:它在发送之前将整个文件读入内存,这对于较大的文件来说确实很糟糕。所以基本上我采取手动分块和检查客户端是否连接每个块后。
context.Response.Clear();
context.Response.BufferOutput = false;
context.Response.ContentType = "application/octet-stream";
context.Response.AddHeader("Content-Disposition", "attachment; filename=" + originalFilename);
context.Response.AddHeader("Content-Length", fileLength.ToString());
context.Response.Cache.SetNoStore();
context.Response.Flush();
downloadFailed = !context.Response.IsClientConnected;
int thisChunk;
long offset = 0;
int chunkSize = 1024 * 8;
byte[] bytes = new byte[chunkSize];
FileStream r = File.OpenRead(localFilename);
while((offset < fileLength) && !downloadFailed)
{
if((fileLength - offset) < chunkSize)
{
thisChunk = (int)(fileLength - offset);
}
else
{
thisChunk = chunkSize;
}
r.Read(bytes, 0, chunkSize);
try
{
context.Response.BinaryWrite(bytes);
context.Response.Flush();
if(!context.Response.IsClientConnected)
{
downloadFailed = true;
}
}
catch(ObjectDisposedException ex1)
{
// Stream is closed, nothing written
break;
}
catch(System.IO.IOException ex3)
{
// I/O error, unknown state, abort
Trace.Write(ex3);
break;
}
offset += thisChunk;
}
if(!downloadFailed)
{
// now update the file, statistics, etc
}
context.Response.Flush();
HttpContext.Current.ApplicationInstance.CompleteRequest();
需要用块大小玩一下才能找到最佳大小。但基本上它可以像这样可靠地工作。
如果发生故障,您不会有任何异常情况吗? – 2010-02-18 05:02:17