如何检测Web客户端是否已成功接收文件?

时间:2010-02-18 02:25:17

标签: c# asp.net iis httpresponse file-transfer

我的问题与this post类似,但我必须使用IIS,ASP.NET和C#执行相同的操作。

如果数据是否已发送,HttpResponse类中的任何方法都不提供反馈,TransmitFile()只是完成其工作(或不工作),并且不提供任何了解结果的方法。< / p>

我在考虑使用.Filter属性,但是再一次,过滤器基于HttpResponseStream,它也没有提供任何反馈。

有什么想法吗?

2 个答案:

答案 0 :(得分:1)

经过一些测试后,我想出了以下解决方案。 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();

需要使用块大小来找到最佳大小。但基本上它可以像这样可靠地工作。

答案 1 :(得分:0)

致电Response.IsClientConnected后检查TransmitFile