2

MVC3 사이트에서 비디오를 제공하고 있는데, 비디오를 반환하는 컨트롤러 동작과 함께 FilePathResult를 반환하며 브라우저에서 재생하려고하면 몇 가지 실망한 문제가 나타납니다. 내 video.js 또는 mediaelement.js 사용 여부에 관계없이.MVC3 동작의 HTML5 비디오가 올바르게 작동하지 않습니다.

    크롬이 진행 막대를 사용하여 위치를 변경하지 않으며, 그것이
  • IE9는
  • 파이어 폭스 남은/경과 표시되지 않습니다 비교적 잘 보인다 완료되면 비디오를 재생할 수 있습니까
  • 시간이 정확하게

그러나 내가 호스트되는 파일에 대한 상대 경로를 제공하면 모두 정상적으로 작동합니다. 동영상은 특정 역할에 속한 사용자 만 사용할 수 있어야하므로 실제 옵션이 아닙니다.

액션 :

[Authorize] 
    public ActionResult Video(string fileName) 
    { 
     var pathBase = Server.MapPath("~/Downloads/Videos/"); 
     var filePath = pathBase + fileName; 
     var contentType = ContentType(fileName); 
     return new FilePathResult(filePath, contentType) { FileDownloadName = fileName }; 
    } 

면도기 :

<!-- @t = the video entity --> 
    <video width="640" height="360" id="@t.Id" poster="@Url.Action("Video", "Download", new { fileName = @t.Poster })" controls="controls" preload="none"> 
     <!-- MP4 source must come first for iOS --> 
     <source src="@Url.Action("Video", "Download", new { fileName = @t.Mp4 })" type='video/mp4' /> 
     <!-- WebM for Firefox 4 and Opera --> 
     <source src="@Url.Action("Video", "Download", new { fileName = @t.WebM })" type='video/webm' /> 
     <!-- OGG for Firefox 3 --> 
     <source src="@Url.Action("Video", "Download", new { fileName = @t.Ogv })" type='video/ogg' /> 
     <!-- Fallback flash player for no-HTML5 browsers with JavaScript turned off --> 
     <object width="640" height="360" type="application/x-shockwave-flash" data="@Url.Content("~/Content/flashmediaelement.swf")">  
      <param name="movie" value="@Url.Content("~/Content/flashmediaelement.swf")" /> 
      <param name="flashvars" value="controls=true&[email protected]("Video", "Download", new { fileName = @t.Poster })&[email protected]("Video", "Download", new { fileName = @t.Mp4 })" />   
      <!-- Image fall back for non-HTML5 browser with JavaScript turned off and no Flash player installed --> 
      <img src="@Url.Action("Video", "Download", new { fileName = @t.Poster })" width="640" height="360" alt="@t.Title" 
       title="No video playback capabilities" /> 
     </object> 
    </video> 
+0

URL이 그들이 완전히 구문 분석 할 때처럼 중요시하는 점은 무엇입니까?를 – heff

+0

download/video? fileName = file.ext – damienc88

답변

3

가 크롬의 문제가 내 핸들러가 지원되지 함께 할 것 같다 비록 내가하는 HTTP 처리기는 이러한 확장을 처리하기 위해 작성 결국 범위 요청.

나를 도울 때 다음 블로그 게시물을 사용했습니다 : http://blogs.visigo.com/chriscoulson/easy-handling-of-http-range-requests-in-asp-net/. 콘텐츠 유형 및 기본 보안을 포함하도록 수정 된 솔루션은 다음과 같습니다.

public void ProcessRequest(HttpContext context) 
    { 
     if (!context.Request.RequestContext.HttpContext.User.Identity.IsAuthenticated) 
      context.Response.Redirect("~"); 
     var path = 
      context.Request.RequestContext.HttpContext.Server.MapPath(
       context.Request.AppRelativeCurrentExecutionFilePath); 
     long size, start, end, length, fp = 0; 
     using (StreamReader reader = new StreamReader(path)) 
     { 

      size = reader.BaseStream.Length; 
      start = 0; 
      end = size - 1; 
      length = size; 
      // Now that we've gotten so far without errors we send the accept range header 
      /* At the moment we only support single ranges. 
      * Multiple ranges requires some more work to ensure it works correctly 
      * and comply with the spesifications: http://www.w3.org/Protocols/rfc2616/rfc2616-sec19.html#sec19.2 
      * 
      * Multirange support annouces itself with: 
      * header('Accept-Ranges: bytes'); 
      * 
      * Multirange content must be sent with multipart/byteranges mediatype, 
      * (mediatype = mimetype) 
      * as well as a boundry header to indicate the various chunks of data. 
      */ 
      context.Response.AddHeader("Accept-Ranges", "0-" + size); 
      context.Response.ContentType = "video/mp4"; 
      // header('Accept-Ranges: bytes'); 
      // multipart/byteranges 
      // http://www.w3.org/Protocols/rfc2616/rfc2616-sec19.html#sec19.2 

      if (!String.IsNullOrEmpty(context.Request.ServerVariables["HTTP_RANGE"])) 
      { 
       long anotherStart = start; 
       long anotherEnd = end; 
       string[] arr_split = 
        context.Request.ServerVariables["HTTP_RANGE"].Split(new char[] {Convert.ToChar("=")}); 
       string range = arr_split[1]; 

       // Make sure the client hasn't sent us a multibyte range 
       if (range.IndexOf(",") > -1) 
       { 
        // (?) Shoud this be issued here, or should the first 
        // range be used? Or should the header be ignored and 
        // we output the whole content? 
        context.Response.AddHeader("Content-Range", "bytes " + start + "-" + end + "/" + size); 
        throw new HttpException(416, "Requested Range Not Satisfiable"); 

       } 

       // If the range starts with an '-' we start from the beginning 
       // If not, we forward the file pointer 
       // And make sure to get the end byte if spesified 
       if (range.StartsWith("-")) 
       { 
        // The n-number of the last bytes is requested 
        anotherStart = size - Convert.ToInt64(range.Substring(1)); 
       } 
       else 
       { 
        arr_split = range.Split(new char[] {Convert.ToChar("-")}); 
        anotherStart = Convert.ToInt64(arr_split[0]); 
        long temp = 0; 
        anotherEnd = (arr_split.Length > 1 && Int64.TryParse(arr_split[1].ToString(), out temp)) 
            ? Convert.ToInt64(arr_split[1]) 
            : size; 
       } 
       /* Check the range and make sure it's treated according to the specs. 
       * http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html 
       */ 
       // End bytes can not be larger than $end. 
       anotherEnd = (anotherEnd > end) ? end : anotherEnd; 
       // Validate the requested range and return an error if it's not correct. 
       if (anotherStart > anotherEnd || anotherStart > size - 1 || anotherEnd >= size) 
       { 

        context.Response.AddHeader("Content-Range", "bytes " + start + "-" + end + "/" + size); 
        throw new HttpException(416, "Requested Range Not Satisfiable"); 
       } 
       start = anotherStart; 
       end = anotherEnd; 

       length = end - start + 1; // Calculate new content length 
       fp = reader.BaseStream.Seek(start, SeekOrigin.Begin); 
       context.Response.StatusCode = 206; 
      } 
     } 
     // Notify the client the byte range we'll be outputting 
     context.Response.AddHeader("Content-Range", "bytes " + start + "-" + end + "/" + size); 
     context.Response.AddHeader("Content-Length", length.ToString()); 
     // Start buffered download 
     context.Response.WriteFile(path, fp, length); 
     context.Response.Flush(); 
    } 
+0

안녕하세요, 위의 코드는 Asp.Net mvc 응용 프로그램에 사용되었으며 네트워크 위치에있는 매우 큰 비디오에서는 작동하지 않는 것 같습니다. 즉 약 2GB 비디오입니다. 나는 IIS7 서버를 사용하고 있으며 브라우저에서 IIS 로의 지연 요청을 보내는 요청에 대한 응답으로 보입니다. 그런 다음 비디오가 부드럽게 재생 된 후. 그러나 내가 추구한다면 그것은 다시 지연 될 것입니다. 내 비디오가 IIS 내부에 있거나 IIS 호스트 된 컴퓨터에있는 경우이 문제가 표시되지 않습니다. – lsc

0

답장을 보내 주셔서 감사합니다.

나는 비슷한 사용 :

internal static void StreamVideo(string fullpath, HttpContextBase context) 
    { 
     long size, start, end, length, fp = 0; 
     using (StreamReader reader = new StreamReader(fullpath)) 
     { 

      size = reader.BaseStream.Length; 
      start = 0; 
      end = size - 1; 
      length = size; 
      // Now that we've gotten so far without errors we send the accept range header 
      /* At the moment we only support single ranges. 
      * Multiple ranges requires some more work to ensure it works correctly 
      * and comply with the spesifications: http://www.w3.org/Protocols/rfc2616/rfc2616-sec19.html#sec19.2 
      * 
      * Multirange support annouces itself with: 
      * header('Accept-Ranges: bytes'); 
      * 
      * Multirange content must be sent with multipart/byteranges mediatype, 
      * (mediatype = mimetype) 
      * as well as a boundry header to indicate the various chunks of data. 
      */ 
      context.Response.AddHeader("Accept-Ranges", "0-" + size); 
      // header('Accept-Ranges: bytes'); 
      // multipart/byteranges 
      // http://www.w3.org/Protocols/rfc2616/rfc2616-sec19.html#sec19.2 

      if (!String.IsNullOrEmpty(context.Request.ServerVariables["HTTP_RANGE"])) 
      { 
       long anotherStart = start; 
       long anotherEnd = end; 
       string[] arr_split = context.Request.ServerVariables["HTTP_RANGE"].Split(new char[] { Convert.ToChar("=") }); 
       string range = arr_split[1]; 

       // Make sure the client hasn't sent us a multibyte range 
       if (range.IndexOf(",") > -1) 
       { 
        // (?) Shoud this be issued here, or should the first 
        // range be used? Or should the header be ignored and 
        // we output the whole content? 
        context.Response.AddHeader("Content-Range", "bytes " + start + "-" + end + "/" + size); 
        throw new HttpException(416, "Requested Range Not Satisfiable"); 

       } 

       // If the range starts with an '-' we start from the beginning 
       // If not, we forward the file pointer 
       // And make sure to get the end byte if spesified 
       if (range.StartsWith("-")) 
       { 
        // The n-number of the last bytes is requested 
        anotherStart = size - Convert.ToInt64(range.Substring(1)); 
       } 
       else 
       { 
        arr_split = range.Split(new char[] { Convert.ToChar("-") }); 
        anotherStart = Convert.ToInt64(arr_split[0]); 
        long temp = 0; 
        anotherEnd = (arr_split.Length > 1 && Int64.TryParse(arr_split[1].ToString(), out temp)) ? Convert.ToInt64(arr_split[1]) : size; 
       } 
       /* Check the range and make sure it's treated according to the specs. 
       * http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html 
       */ 
       // End bytes can not be larger than $end. 
       anotherEnd = (anotherEnd > end) ? end : anotherEnd; 
       // Validate the requested range and return an error if it's not correct. 
       if (anotherStart > anotherEnd || anotherStart > size - 1 || anotherEnd >= size) 
       { 
        context.Response.ContentType = MimeMapping.GetMimeMapping(fullpath); 
        context.Response.AddHeader("Content-Range", "bytes " + start + "-" + end + "/" + size); 
        throw new HttpException(416, "Requested Range Not Satisfiable"); 
       } 
       start = anotherStart; 
       end = anotherEnd; 

       length = end - start + 1; // Calculate new content length 
       fp = reader.BaseStream.Seek(start, SeekOrigin.Begin); 
       context.Response.StatusCode = 206; 
      } 
     } 
     // Notify the client the byte range we'll be outputting 
     context.Response.AddHeader("Content-Range", "bytes " + start + "-" + end + "/" + size); 
     context.Response.AddHeader("Content-Length", length.ToString()); 
     // Start buffered download 
     context.Response.WriteFile(fullpath, fp, length); 
     context.Response.End(); 

    } 
관련 문제