title: c# streaming over http to iphone
body: <p>i am trying to stream video over http to iphone without a streming server with .net.
  After some tests i found that if you just upload iphone compatible video to your server, iis7 works just fine and iphone startsplaying video after small buffer time and continues to download in the background.</p>
  
  <p>My problem is, i am unable to do it with .net. I have tried with </p>
  
  <pre><code>    public static void SmallFile(string filename, string filepath, string contentType)
  {
      try
      {
          FileStream MyFileStream = new FileStream(filepath, FileMode.Open, FileAccess.Read, FileShare.Read);
          long FileSize;
          FileSize = MyFileStream.Length;
          byte[] Buffer = new byte[(int)FileSize];
          MyFileStream.Read(Buffer, 0, (int)MyFileStream.Length);
          MyFileStream.Close();
          HttpContext.Current.Response.ContentType = contentType;
          HttpContext.Current.Response.AddHeader("Content-Disposition", "attachment;filename=" + HttpUtility.UrlEncode(filename, System.Text.Encoding.UTF8));
          HttpContext.Current.Response.BinaryWrite(Buffer);
  
      }
      catch
      {
          HttpContext.Current.Response.ContentType = "text/html";
          HttpContext.Current.Response.Write("Downloading Error! " + filename + " not found!");
      }
      HttpContext.Current.Response.End();
  }
  </code></pre>
  
  <p>or with</p>
  
  <pre><code>public static void ResumableFile(string filename, string fullpath, string contentType)
  {
      try
      {
          FileStream myFile = new FileStream(fullpath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
          BinaryReader br = new BinaryReader(myFile);
          try
          {
              HttpContext.Current.Response.AddHeader("Accept-Ranges", "bytes");
              HttpContext.Current.Response.Buffer = false;
              long fileLength = myFile.Length;
              long startBytes = 0;
  
              //int pack = 10240; //10K bytes
              int pack = 1048576; //1024K bytes
              if (HttpContext.Current.Request.Headers["Range"] != null)
              {
                  HttpContext.Current.Response.StatusCode = 206;
                  string[] range = HttpContext.Current.Request.Headers["Range"].Split(new char[] { '=', '-' });
                  startBytes = Convert.ToInt64(range[1]);
              }
              HttpContext.Current.Response.AddHeader("Content-Length", (fileLength - startBytes).ToString());
              if (startBytes != 0)
              {
                  HttpContext.Current.Response.AddHeader("Content-Range", string.Format(" bytes {0}-{1}/{2}", startBytes, fileLength - 1, fileLength));
              }
              HttpContext.Current.Response.AddHeader("Connection", "Keep-Alive");
              HttpContext.Current.Response.ContentType = contentType;
              HttpContext.Current.Response.AddHeader("Content-Disposition", "attachment;filename=" + HttpUtility.UrlEncode(filename, System.Text.Encoding.UTF8));
  
              br.BaseStream.Seek(startBytes, SeekOrigin.Begin);
              int maxCount = (int)Math.Floor((double)((fileLength - startBytes) / pack)) + 1;
  
              for (int i = 0; i &lt; maxCount; i++)
              {
                  if (HttpContext.Current.Response.IsClientConnected)
                  {
                      HttpContext.Current.Response.BinaryWrite(br.ReadBytes(pack));
                      }
                  else
                  {
                      i = maxCount;
                  }
              }
          }
          catch
          {
              HttpContext.Current.Response.ContentType = "text/html";
              HttpContext.Current.Response.Write("Downloading Error! " + filename + " not found!");
          }
          finally
          {
              br.Close();
              myFile.Close();
          }
      }
      catch
      {
          HttpContext.Current.Response.ContentType = "text/html";
          HttpContext.Current.Response.Write("Downloading Error!" + filename + " not found!");
      }
  }
  </code></pre>
  
  <p>In both, i get error saying server is not configured properly. I then removed </p>
  
  <pre><code> HttpContext.Current.Response.AddHeader("Content-Disposition", "attachment; filename=" + HttpUtility.UrlEncode(filename, System.Text.Encoding.UTF8));
  </code></pre>
  
  <p>part so it won't trigger full download but result was the same.</p>
  
  <p>I have checked responses from server and there is no different/extra header coming from server when i directly download file.</p>
  
  <p>What i am trying to findout what would be enabling iphone to buffer and start playing video when i directly download video file and how can i implemnet it with .net</p>
  
  <p>If youwonder why i just don't use iis, i need to put some sort of leech protecttion due to bandwidth restrictions</p>
  
  <p>Anyone have any exprience?</p>
  
  <p><strong>UPDATE</strong></p>
  
  <p>Here is the first request and response from iis</p>
  
  <pre><code>GET /test.mp4 HTTP/1.1
  Host: 192.168.2.200
  User-Agent: Mozilla/5.0 (iPhone; U; CPU iPhone OS 3_1_2 like Mac OS X; tr-tr) AppleWebKit/528.18 (KHTML, like Gecko) Version/4.0 Mobile/7D11 Safari/528.16
  Cache-Control: max-age=0
  Accept: application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
  Accept-Language: tr-tr
  Accept-Encoding: gzip, deflate
  Connection: keep-alive
  
  
  HTTP/1.1 200 OK
  Content-Type: video/mp4
  Last-Modified: Wed, 23 Dec 2009 20:12:57 GMT
  Accept-Ranges: bytes
  ETag: "e6ad9151c84ca1:0"
  Server: Microsoft-IIS/7.5
  X-Powered-By: ASP.NET
  Date: Wed, 23 Dec 2009 21:07:19 GMT
  Content-Length: 2301438
  </code></pre>
  
  <p><strong>And second request and response</strong></p>
  
  <pre><code>GET /test.mp4 HTTP/1.1
  Host: 192.168.2.200
  Range: bytes=0-2269183
  Connection: close
  User-Agent: Apple iPhone OS v3.1.2 CoreMedia v1.0.0.7D11
  Accept: */*
  Accept-Encoding: identity
  
  
  
  HTTP/1.1 206 Partial Content
  Content-Type: video/mp4
  Last-Modified: Wed, 23 Dec 2009 20:12:57 GMT
  Accept-Ranges: bytes
  ETag: "e6ad9151c84ca1:0"
  Server: Microsoft-IIS/7.5
  X-Powered-By: ASP.NET
  Date: Wed, 23 Dec 2009 21:11:33 GMT
  Connection: close
  Content-Length: 2269184
  Content-Range: bytes 0-2269183/2301438
  </code></pre>
  
  <p>As i understand iphone requests different bytes on second request and so on. 
  Is there anyway getting c# to send those bytes range to the client?</p>