2014-11-04 16 views
0

我有一个充当文件主机的类,本质上你用这个端口号启动这个类,并且它托管一个文件(在真实世界中,实际上是包含很多部分的较大文件的主机部分 - 但是我已经考虑到这一点,试图找到一些问题的底部)。当我托管一个小文件时,没有问题,并且所有功能都按预期工作,当我托管较大的文件时,我收到了一些不寻常的行为 - 特别是当我使用Windows Media Player向侦听器打开网址时。看起来,Windows媒体播放器发送获取请求以获取所有内容,然后发出第二个请求开始收集块 - 但这些总是导致“指定的网络无法找到”的例外。幸运的是,原始连接保持打开状态,并且文件在媒体播放器中运行 - 但是如果我然后尝试将滑块移动到文件中的特定点,它会触发另一个错误输出的请求 - 我设法让它显示窗口媒体根本不会让你移动滑块 - 但这对我们的目的不起作用。我已经尝试了在IIS中托管的相同文件,并且它看起来很好,并且嗅探了数据包和匹配(至少在httplistener死亡之前)...我错过了什么。HTTPListener类似乎在新建的时候切断旧连接,这是否正确?

这里是我使用的代码:

using SWAT.Apps.WebinarRecordingsViewer.Interfaces; 
using System; 
using System.Collections.Generic; 
using System.IO; 
using System.Linq; 
using System.Net; 
using System.Text; 
using System.Threading.Tasks; 

namespace SWAT.Apps.WebinarRecordingsViewer.Implementation.Common 
{ 
public class FileHost : IFileHost 
{ 

    private long Port { get; set; } 
    private string MimeType { get; set; } 
    private PointerRecord PointerRecord { get; set; } 
    public string FileName { get; set; } 
    public string ResultingFilename { get; set; } 

    public virtual string Url 
    { 
     get 
     { 
      return "http://localhost:" + this.Port + "/"; 
     } 
    } 

    public Guid Guid { get; set; } 

    public FileHost(string filename, PointerRecord pointerRecord, string mimeType, long port, string resultingFilename, string realurl) 
    { 
     this.Port = port; 
     this.MimeType = mimeType; 
     this.FileName = filename; 
     this.PointerRecord = pointerRecord; 
     this.ResultingFilename = resultingFilename; 
     this.RealUrl = realurl; 
     this.Guid = Guid.NewGuid(); 
    } 


    public void Dispose() 
    { 
     this.Stop(); 
    } 


    private bool Stopped { get; set; } 
    private bool Stopping { get; set; } 

    public void Stop() 
    { 
     if (!Stopped) 
     { 
      Stopping = true; 
      if (this.listener!=null) 
      { 
       this.listener.Abort(); 

      } 

     } 
     this.listener.Close(); 


    } 
    public HttpListener listener { get; set; } 


    public void Start() 
    { 
     Stopped = false; 
     Stopping = false; 

     this.listener = new HttpListener(); 
     this.listener.Prefixes.Add(string.Format("http://localhost:{0}/", this.Port)); 
     this.listener.Start(); 
     IAsyncResult result = listener.BeginGetContext(new AsyncCallback(ListenerCallback), this.listener); 
     } 



    public void ListenerCallback(IAsyncResult result) 
    { 
     if (this.listener == null) 
      return; 
     HttpListenerContext context = this.listener.EndGetContext(result); 

     // Call EndGetContext to complete the asynchronous operation. 
     if (!Stopping) 
     { 
      this.listener.BeginGetContext(new AsyncCallback(ListenerCallback), this.listener); 
      this.WriteFile(context.Response, context.Request); 

     } 
     if (Stopping) 
     { 
      Stopped = true; 
      Stopping = false; 

     } 

    } 

    public string RealUrl { get; set; } 

    private void WriteFile(HttpListenerResponse response, HttpListenerRequest request) 
    { 
     using (FileStream fs = File.Open(/*this.FileName*/"f:\\work\\download.wmv",FileMode.Open, FileAccess.Read, FileShare.Read)) 
     { 
       response.KeepAlive = true; 
      response.SendChunked = true; 
      bool doingRange = false; 
     //  response.AddHeader("Last-Modified", "Sun, 14 Nov 2010 21:15:21 GMT"); 
     // response.ProtocolVersion = new Version("1.1"); 
    //  response.AddHeader("Cache-Control", "max-age=86400"); 
    //  response.AddHeader("ETag", string.Format("\"{0}\"", this.Guid.ToString())); 
      response.AddHeader("Accept-Ranges", "bytes"); 
      response.ContentType = this.MimeType; 
      long start = 0; 
      long length = fs.Length;//this.PointerRecord.Length; 
      Int64 endByte = length-1; 
      if (request.Headers["range"] != null) 
      { 
       doingRange = true; 
       start = long.Parse(request.Headers["range"].Split('=')[1].Split('-')[0].Trim()) ; 
       if ((request.Headers["range"].Split('=')[1].Split('-').Length > 1)) 
       { 
        Int64 endread = 0; 
        Int64.TryParse(request.Headers["range"].Split('=')[1].Split('-')[1].Trim(), out endread); 
        if (endread > 0) 
        { 
         endByte = endread; 
        } 

       } 
       if ((endByte + 1) > this.PointerRecord.Length) 
       { 
        endByte = this.PointerRecord.Length - 1; 
       } 

       length = (endByte - start) + 1; 
       response.AddHeader("Content-Range", "bytes=" + start.ToString() + "-" + endByte.ToString() + "/" + fs.Length.ToString()); 
       response.ContentLength64 = length; 

      } 
      else 
      { 
       response.ContentLength64 = fs.Length; 


      } 

      byte[] buffer = new byte[1024 * 1024 ]; 

      fs.Seek(start, SeekOrigin.Begin); 

      long read =0; 
      long runningTotal = 0; 
      try 
      { 
       var stream = response.OutputStream; 
       while ((length > 0) && ((read = fs.Read(buffer, 0, buffer.Length)) > 0)) 
       { 
        runningTotal += read; 
        // if the read overshoots the requested read length 
        if (runningTotal > length) 
        { 
         read = read - (runningTotal - length); 
        } 
        stream.Write(buffer, 0, Convert.ToInt32(read)); 
        stream.Flush(); 
        if (runningTotal >= length) 
        { 
         break; 
        } 



       } 
       stream.Close(); 
       response.StatusCode = doingRange ? (int)HttpStatusCode.PartialContent : (int)HttpStatusCode.OK; 
       response.StatusDescription = (doingRange ? HttpStatusCode.PartialContent : HttpStatusCode.OK).ToString(); 

      } 
      catch (Exception ex) 
      { 
       var test = ex.Message; 


      } 
      finally 
      { 
       fs.Close(); 
       fs.Dispose(); 
      } 


     } 
    } 




    public event EventHandler<FileHostEventArgs> Error; 

    public void OnError(FileDownloadEventArgs e) 
    { 
     throw new NotImplementedException(); 
    } 
} 
} 

我不相信这是媒体播放器的行为不端,还是它的东西在服务器代码...任何帮助/建议将是巨大的..

回答

0

原来的媒体播放器是超级挑剔,而IE浏览器只是让这一点去:我做了一个错字

response.AddHeader("Content-Range", "bytes=" + start.ToString() + "-" + endByte.ToString() + "/" + fs.Length.ToString()); 

应该是:

response.AddHeader("Content-Range", "bytes " + start.ToString() + "-" + endByte.ToString() + "/" + fs.Length.ToString());