13

HttpHandler から Web フォームで大きなファイルをストリーミングしようとしています。ファイルをストリーミングしていないため、機能していないようです。代わりに、ファイルをメモリに読み込み、クライアントに送り返します。私は解決策を探していますが、解決策は、同じことをしているときにファイルをストリーミングしていることを示しています。ストリーミングする私の解決策は次のとおりです。

using (Stream fileStream = File.OpenRead(path))
{
    context.Response.Cache.SetExpires(DateTime.UtcNow.AddMinutes(360.0));
    context.Response.Cache.SetCacheability(HttpCacheability.Public);
    context.Response.AppendHeader("Content-Type", "video/mp4");
    context.Response.AppendHeader("content-length", file.Length);
    byte[] buffer = new byte[1024];
    while (true)
    {
      if (context.Response.IsClientConnected)
     {
       int bytesRead = fileStream.Read(buffer, 0, buffer.Length);
       if (bytesRead == 0) break;
       context.Response.OutputStream.Write(buffer, 0, bytesRead);
       context.Response.Flush();
     }
     else
     {
       break;
     }

   }
   context.Response.End();
}

コードをデバッグすると小さなファイルの場合に何が起こっているかというと、ビデオは再生されますが、context.Respond.End() 行に到達するまでは再生されません。ただし、大きなファイルの場合、ファイル全体をメモリに保存して問題を引き起こすため、これは機能しません。

4

3 に答える 3

18

同様の問題があり、再生する前にビデオを完全にダウンロードする必要がありました。

具体的には、動画をストリーミングしたいことがわかります。エンコーディングには注意する必要があります (ストリーミング可能であることを確認してください)。ファイルを作成した人が奇妙な方法でビデオを作成した可能性があるため、拡張子だけに依存しないでください。良い。mediainfoを使用します。あなたの場合、H.264である必要があります。

また、ブラウザとストリーミングに使用するもの (バックエンド コード以外) にも依存します。私の場合、Chrome/Html5 と .webm (VP8/Ogg Vorbis) を使用しました。1Gを超えるファイルで機能しています。4G以上はテストしていません...

ビデオのダウンロードに使用するコード:

    public void Video(string folder, string name) {
        string filepath = Server.MapPath(String.Format("{0}{1}", HttpUtility.UrlDecode(folder), name));
        string filename = name;

        System.IO.Stream iStream = null;
        byte[] buffer = new Byte[4096];
        int length;
        long dataToRead;

        try {
            // Open the file.
            iStream = new System.IO.FileStream(filepath, System.IO.FileMode.Open,
                        System.IO.FileAccess.Read, System.IO.FileShare.Read);


            // Total bytes to read:
            dataToRead = iStream.Length;

            Response.AddHeader("Accept-Ranges", "bytes");
            Response.ContentType = MimeType.GetMIMEType(name);

            int startbyte = 0;

            if (!String.IsNullOrEmpty(Request.Headers["Range"])) {
                string[] range = Request.Headers["Range"].Split(new char[] { '=', '-' });
                startbyte = Int32.Parse(range[1]);
                iStream.Seek(startbyte, SeekOrigin.Begin);

                Response.StatusCode = 206;
                Response.AddHeader("Content-Range", String.Format(" bytes {0}-{1}/{2}", startbyte, dataToRead - 1, dataToRead));
            }

            while (dataToRead > 0) {
                // Verify that the client is connected.
                if (Response.IsClientConnected) {
                    // Read the data in buffer.
                    length = iStream.Read(buffer, 0, buffer.Length);

                    // Write the data to the current output stream.
                    Response.OutputStream.Write(buffer, 0, buffer.Length);
                    // Flush the data to the HTML output.
                    Response.Flush();

                    buffer = new Byte[buffer.Length];
                    dataToRead = dataToRead - buffer.Length;
                } else {
                    //prevent infinite loop if user disconnects
                    dataToRead = -1;
                }
            }
        } catch (Exception ex) {
            // Trap the error, if any.
            Response.Write("Error : " + ex.Message);
        } finally {
            if (iStream != null) {
                //Close the file.
                iStream.Close();
            }
            Response.Close();
        }
    }

応答ヘッダーに必要なものがすべて含まれていることを確認してください。

于 2013-05-31T18:26:20.747 に答える