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

发布于 2024-08-22 04:01:59 字数 418 浏览 4 评论 0原文

我的问题类似于 这篇文章,但我必须使用 IIS、ASP.NET 和 C# 执行相同的操作。

如果数据已发送或未发送,HttpResponse 类中的任何方法都不会提供反馈,TransmitFile() 只是执行其工作(或不执行),并且不提供任何方法知道结果。

我正在考虑使用 .Filter 属性,但话又说回来,过滤器基于 HttpResponseStream ,它也不提供任何反馈。

有什么想法吗?

My question is similar to this post but I have to do the same using IIS, ASP.NET, and C#.

None of the methods in the HttpResponse class provide feedback if the data was sent or not, TransmitFile() just does its job (or not) and does not provide any means of knowing the result.

I was thinking of using the .Filter property but then again, the filter is based on the HttpResponseStream which does also not provide any feedback.

Any ideas?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

溇涏 2024-08-29 04:01:59

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

需要对块大小进行一些调整才能找到最佳大小。但基本上它是这样可靠地工作的。

After some testing I came up with the following solution to the problem. TransmitFile() has one serious limitation: it reads the whole file into memory before sending, this is really bad for larger files. So basically I resorted to manual chunking and checking if the client is connected after each chunk.

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();

Will need to play a bit with the chunk size to find the optimal size. But basically it works reliably like this.

独夜无伴 2024-08-29 04:01:59

调用 TransmitFile 后检查 Response.IsClientConnected

Check Response.IsClientConnected after calling TransmitFile.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文