本文介绍了服务大文件和C#的HttpListener的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想使用的HttpListener为静态文件,这工作得很好用的小文件。当文件大小越来越大(350和600MB的文件进行测试),服务器有以下例外之一扼流圈:


HttpListenerException 的我/ O操作,因为线程退出或应用程序请求的被终止,或者:

HttpListenerException 信号灯超时时间已过期

I'm trying to use HttpListener to serve static files, and this works well with small files. When file sizes grow larger (tested with 350 and 600MB files), the server chokes with one of the following exceptions:

HttpListenerException: The I/O operation has been aborted because of either a thread exit or an application request, or:
HttpListenerException: The semaphore timeout period has expired.

有什么需要改变,以摆脱异常,并让它运行稳定/可靠的(和快速)?

What needs to be changed to get rid of the exceptions, and let it run stable/reliable (and fast)?

下面是一些进一步的阐述:这基本上是一个后续问题的。代码被稍微延伸到显示效果。内容写作是与(希望合理的)的块大小,64kB的在我的案件,但改变的价值没有做,除了速度差异(参见提到旧的问题),一个循环。

Here's some further elaboration: This is basically a follow-up question to this earlier question. The code is slightly extended to show the effect. Content writing is in a loop with (hopefully reasonable) chunk sizes, 64kB in my case, but changing the value didn't make a difference except speed (see the mentioned older question).


using( FileStream fs = File.OpenRead( @"C:\test\largefile.exe" ) ) {

    //response is HttpListenerContext.Response...
    response.ContentLength64 = fs.Length;
    response.SendChunked = false;
    response.ContentType = System.Net.Mime.MediaTypeNames.Application.Octet;
    response.AddHeader( "Content-disposition", "attachment; filename=largefile.EXE" );

    byte[] buffer = new byte[ 64 * 1024 ];
    int read;
    using( BinaryWriter bw = new BinaryWriter( response.OutputStream ) ) {
        while( ( read = fs.Read( buffer, 0, buffer.Length ) ) > 0 ) {
            Thread.Sleep( 200 ); //take this out and it will not run
            bw.Write( buffer, 0, read );
            bw.Flush(); //seems to have no effect
        }

        bw.Close();
    }

    response.StatusCode = ( int )HttpStatusCode.OK;
    response.StatusDescription = "OK";
    response.OutputStream.Close();
}



我想在浏览器中,并在C#程序中使用的下载HttpWebRequest的,没有区别。

I'm trying the download in a browser and also in a C# program using HttpWebRequest, it makes no difference.

根据我的研究,我想这的HttpListener是不是真的能够刷新内容发送到客户端或按照自己的速度,至少这样做。我也离开了的BinaryWriter,直接写信给流 - 没有什么区别。介绍基本流周围BufferedStream - 没有区别。够滑稽的,如果一个Thread.sleep代码(200)或稍大于环介绍,它适用于我的盒子。不过,我怀疑它是一个真正的解决方案不够稳定。 给人的感觉是有一点机会都没有得到它运行正常(除了移动到IIS / ASP.NET,我将诉诸,但更可能留远离如果可能的话)。

Based on my research, I suppose that HttpListener is not really able to flush contents to the client or at least does so at its own pace. I have also left out the BinaryWriter and wrote directly to the stream - no difference. Introduced a BufferedStream around the base stream - no difference. Funny enough, if a Thread.Sleep(200) or slightly larger is introduced in the loop, it works on my box. However I doubt it is stable enough for a real solution. This question gives the impression that there's no chance at all to get it running correctly (besides moving to IIS/ASP.NET which I would resort to, but more likely stay away from if possible).

推荐答案

你没向我们展示你如何初始化的HttpListener另一重要组成部分。因此,我试着用如下的代码和它的工作。

You didn't show us the other critical part how you initialized HttpListener. Therefore I tried your code with the one below and it worked

HttpListener listener = new HttpListener();
listener.Prefixes.Add("http://*:8080/");
listener.Start();
Task.Factory.StartNew(() =>
{
    while (true)
    {
        HttpListenerContext context = listener.GetContext();
        Task.Factory.StartNew((ctx) =>
        {
            WriteFile((HttpListenerContext)ctx, @"C:\LargeFile.zip");
        }, context,TaskCreationOptions.LongRunning);
    }
},TaskCreationOptions.LongRunning);



WriteFile的是你的代码,其中 Thread.sleep代码(200); 被删除

WriteFile is your code where Thread.Sleep( 200 ); is removed.

如果你想看到它的完整代码

If you want to see the full code of it.

void WriteFile(HttpListenerContext ctx, string path)
{
    var response = ctx.Response;
    using (FileStream fs = File.OpenRead(path))
    {
        string filename = Path.GetFileName(path);
        //response is HttpListenerContext.Response...
        response.ContentLength64 = fs.Length;
        response.SendChunked = false;
        response.ContentType = System.Net.Mime.MediaTypeNames.Application.Octet;
        response.AddHeader("Content-disposition", "attachment; filename=" + filename);

        byte[] buffer = new byte[64 * 1024];
        int read;
        using (BinaryWriter bw = new BinaryWriter(response.OutputStream))
        {
            while ((read = fs.Read(buffer, 0, buffer.Length)) > 0)
            {
                bw.Write(buffer, 0, read);
                bw.Flush(); //seems to have no effect
            }

            bw.Close();
        }

        response.StatusCode = (int)HttpStatusCode.OK;
        response.StatusDescription = "OK";
        response.OutputStream.Close();
    }
}

这篇关于服务大文件和C#的HttpListener的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

06-23 01:43