1 緣由分析chrome
https://www.zhihu.com/question/41818719ide
2 代碼實現spa
1 注意點: 請求時 : header中 range 請求多少長度 代碼要返回相應的長度 好比Byte 0-1code
/// <summary> /// 返回mp4 兼容蘋果 /// </summary> /// <param name="context"></param> /// <param name="filePath"></param> private void CreateVideoResponse(HttpContext context, string filePath) { var reqRange = context.Request.Headers["Range"]; string[] reqBlockRange = null; if (!string.IsNullOrEmpty(reqRange)) { reqBlockRange = reqRange.Replace("bytes=", "").Split(new[] { "-"},StringSplitOptions.RemoveEmptyEntries); context.Response.StatusCode = 206; context.Response.AddHeader("status", "206"); } using (var stream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) using (var reader = new BinaryReader(stream)) { long fileSize = stream.Length; long startPosition = 0; long partialSize = fileSize; if (reqBlockRange != null) {
//safari startPosition = Convert.ToInt64(reqBlockRange[0]); if(reqBlockRange.Length > 1) { long endPosition = fileSize; if (long.TryParse(reqBlockRange[1], out endPosition)) { partialSize = endPosition - startPosition + 1; } }else {
// chrome 等 partialSize = fileSize - startPosition; } } byte[] buffer = new byte[(int)partialSize]; reader.BaseStream.Seek(startPosition, SeekOrigin.Begin); reader.Read(buffer, 0, (int)partialSize); context.Response.AddHeader("accept-ranges", "bytes"); context.Response.AddHeader("access-control-allow-methods", "HEAD, GET, OPTIONS"); context.Response.AddHeader("cache-control", "public, max-age=30726563"); context.Response.ContentType = "video/mp4"; context.Response.Cache.SetLastModified(DateTime.Now); context.Response.AddHeader("Connection", "keep-alive"); context.Response.AddHeader("content-range", $"bytes {startPosition}-{startPosition + partialSize-1 }/{fileSize}"); context.Response.AddHeader("Content-Length", $"{partialSize}"); context.Response.BinaryWrite(buffer); } }