I am trying to create a test page which will contain a HTML5 VIDEO tag which will allow converted videos to be played. I am successfully able to convert the videos and store these locally on the server but I'd like to be able to stream all videos through another .aspx page.
我正在尝试创建一个测试页面,它将包含一个HTML5视频标签,可以播放转换后的视频。我能够成功地转换视频并将它们存储在服务器上,但是我希望能够通过另一个.aspx页面来传输所有视频。
Assuming I have a player.aspx page which will contain the HTML code and getvideo.aspx page which will do nothing except provide the video binary, I thought that the following code would work fine in my player.aspx page:
假设我有一个玩家。aspx页面将包含HTML代码和getvideo。aspx页面除了提供视频二进制文件之外什么都不做,我认为下面的代码在我的播放器中会很好。aspx页面:
<div style="text-align:center">
<video controls autoplay id="video1" width="920">
<source src="http://www.mywebsite.com/getvideo.aspx?getvideo=1" type="video/mp4">
Your browser does not support HTML5 video.
</video>
The getvideo.aspx page contains the following vb.net code:
getvideo。aspx页面包含以下vb.net代码:
Response.clearheaders
Response.AddHeader("Content-Type", "video/mp4")
Response.AddHeader("Content-Disposition", "inline;filename=""newvideo.mp4""")
dim Err as string = ""
Dim iStream As System.IO.Stream
' Buffer to read 10K bytes in chunk:
Dim buffer(buffersize) As Byte
' Length of the file:
Dim length As Integer
' Total bytes to read:
Dim dataToRead As Long
' Identify the file to download including its path.
Dim filepath As String = "./outout/videos/newvideo.mp4"
' Identify the file name.
Dim filename As String = System.IO.Path.GetFileName(filepath)
' Open the file.
try
iStream = New System.IO.FileStream(filepath, System.IO.FileMode.Open, IO.FileAccess.Read, IO.FileShare.Read)
catch ex as exception
throw new exception("Could not create FileStream for [" & filepath & "], error follows." & vbcrlf & ex.toString)
end try
Try
' Total bytes to read:
dataToRead = iStream.Length
' Read the bytes.
While dataToRead > 0
' Verify that the client is connected.
If system.web.httpcontext.current.Response.IsClientConnected Then
' Read the data in buffer
length = iStream.Read(buffer, 0, buffersize)
' Write the data to the current output stream.
system.web.httpcontext.current.Response.OutputStream.Write(buffer, 0, length)
' Flush the data to the HTML output.
system.web.httpcontext.current.Response.Flush()
ReDim buffer(buffersize) ' Clear the buffer
dataToRead = dataToRead - length
Else
'prevent infinite loop if user disconnects
dataToRead = -1
End If
End While
Catch ex As Exception
' Trap the error, if any.
err = "Error accessing " & filepath & " : " & ex.tostring
Finally
If IsNothing(iStream) = False Then
' Close the file.
iStream.Close()
End If
End Try
if err<>"" then throw new exception( err )
All I get on my page output is a HTML video player (chrome's basic player) which seems to time out and the PLAY button goes grey. The Network tool in the Chrome Developer tools shows that it's downloading 45mb and gets a 200 response code. This suggests to me that it is working fine. Although I get a second GET request with the status of "Cancelled"?
我的页面输出是一个HTML视频播放器(chrome的基本播放器),它似乎超时了,播放按钮变为灰色。Chrome开发工具中的网络工具显示它正在下载45mb,并获得200个响应代码。这说明它运行良好。虽然我得到了第二个get请求,但是“取消”的状态?
If I visit www.mywebsite.com/output/videos/myvideo.mp4 then this plays in the browser fine so I know IIS is configured to correctly stream video.
如果我访问www.mywebsite.com/output/videos/myvideo.mp4,这在浏览器中运行良好,所以我知道IIS配置为正确的流视频。
Also if I change the response content disposition to "attachment" then the browser correctly forces a download of the video when going to my ASPX page, but this also doesn't correctly play on the HTML player. Is there something 'clever' going on with the HTML5 VIDEO tag which is stopping a .aspx file from serving up video via .net? Or am I missing a response header?
另外,如果我将响应内容配置更改为“附件”,那么浏览器在我的ASPX页面上正确地强制下载视频,但这也不能正确地在HTML播放器上播放。HTML5视频标签有什么“聪明”的地方吗?它阻止了。aspx文件通过。net提供视频。还是我缺少一个响应头?
Thanks!
谢谢!
1 个解决方案
#1
3
FIXED!
固定!
The problem here is presumably something to do with the HTML5 video implementation of range-requests. Without supporting range-requests in the page being used to SERVE the video, they just won't work.
这里的问题可能与HTML5的距离请求视频实现有关。如果不支持用于视频的页面中的范围请求,它们就无法工作。
It was this very helpful post from Scott Mitchell which set me on the case: http://dotnetslackers.com/articles/aspnet/Range-Specific-Requests-in-ASP-NET.aspx
Scott Mitchell的这篇非常有用的文章让我想到了这个问题:http://dotnetslackers.com/articles/aspnet/range - specific - requests-inasp-net.aspx
And another helpful post from Chris Coulson which provided the implementation in C# for the solution! http://blogs.visigo.com/chriscoulson/easy-handling-of-http-range-requests-in-asp-net/
Chris Coulson提供的另一篇有用的文章,在c#中提供了解决方案的实现!http://blogs.visigo.com/chriscoulson/easy-handling-of-http-range-requests-in-asp-net/
My vb.net port of the code Chris found is below, to implement it simply put this in your page:
我的vb.net端口的代码克里斯发现如下,为了实现它只需把这个放在你的页面:
system.web.httpcontext.current.Response.ContentType = "video/" & convertFormat.toString
RangeDownload(convertedVideo, system.web.httpcontext.current)
VB.NET CODE:
VB。NET代码:
private sub RangeDownload( fullpath as string, context as HttpContext)
dim size as long
dim start as long
dim theend as long
dim length as long
dim fp as long =0
using reader as new StreamReader(fullpath)
size = reader.BaseStream.Length
start = 0
theend = 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 (not String.IsNullOrEmpty(context.Request.ServerVariables("HTTP_RANGE"))) then
dim anotherStart as long = start
dim anotherEnd as long = theend
dim arr_split as string() = context.Request.ServerVariables("HTTP_RANGE").Split("=") 'new char[] { Convert.ToChar("=") })
dim range as string = arr_split(1)
'// Make sure the client hasn't sent us a multibyte range
if (range.IndexOf(",") > -1) then
'// (?) 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 & "-" & theend & "/" & size)
throw new HttpException(416, "Requested Range Not Satisfiable")
end if
'// 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("-")) then
'// The n-number of the last bytes is requested
anotherStart = size - Convert.ToInt64(range.Substring(1))
else
arr_split = range.Split("-")
anotherStart = Convert.ToInt64(arr_split(0))
dim temp as long = 0
if (arr_split.Length > 1 andalso Int64.TryParse(arr_split(1).ToString(), temp)) then
anotherEnd = Convert.ToInt64(arr_split(1))
else
anotherEnd = size
end if
end if
'/* 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.
if (anotherEnd > theend) then
anotherEnd = theend
else
anotherEnd = anotherEnd
end if
'// Validate the requested range and return an error if it's not correct.
if (anotherStart > anotherEnd or anotherStart > size - 1 or anotherEnd >= size) then
context.Response.AddHeader("Content-Range", "bytes " + start + "-" + theend + "/" + size)
throw new HttpException(416, "Requested Range Not Satisfiable")
end if
start = anotherStart
theend = anotherEnd
length = theend - start + 1 '// Calculate new content length
fp = reader.BaseStream.Seek(start, SeekOrigin.Begin)
context.Response.StatusCode = 206
end if
end using
'// Notify the client the byte range we'll be outputting
context.Response.AddHeader("Content-Range", "bytes " & start & "-" & theend & "/" & size)
context.Response.AddHeader("Content-Length", length.ToString())
'// Start buffered download
context.Response.WriteFile(fullpath, fp, length)
context.Response.End()
end sub
#1
3
FIXED!
固定!
The problem here is presumably something to do with the HTML5 video implementation of range-requests. Without supporting range-requests in the page being used to SERVE the video, they just won't work.
这里的问题可能与HTML5的距离请求视频实现有关。如果不支持用于视频的页面中的范围请求,它们就无法工作。
It was this very helpful post from Scott Mitchell which set me on the case: http://dotnetslackers.com/articles/aspnet/Range-Specific-Requests-in-ASP-NET.aspx
Scott Mitchell的这篇非常有用的文章让我想到了这个问题:http://dotnetslackers.com/articles/aspnet/range - specific - requests-inasp-net.aspx
And another helpful post from Chris Coulson which provided the implementation in C# for the solution! http://blogs.visigo.com/chriscoulson/easy-handling-of-http-range-requests-in-asp-net/
Chris Coulson提供的另一篇有用的文章,在c#中提供了解决方案的实现!http://blogs.visigo.com/chriscoulson/easy-handling-of-http-range-requests-in-asp-net/
My vb.net port of the code Chris found is below, to implement it simply put this in your page:
我的vb.net端口的代码克里斯发现如下,为了实现它只需把这个放在你的页面:
system.web.httpcontext.current.Response.ContentType = "video/" & convertFormat.toString
RangeDownload(convertedVideo, system.web.httpcontext.current)
VB.NET CODE:
VB。NET代码:
private sub RangeDownload( fullpath as string, context as HttpContext)
dim size as long
dim start as long
dim theend as long
dim length as long
dim fp as long =0
using reader as new StreamReader(fullpath)
size = reader.BaseStream.Length
start = 0
theend = 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 (not String.IsNullOrEmpty(context.Request.ServerVariables("HTTP_RANGE"))) then
dim anotherStart as long = start
dim anotherEnd as long = theend
dim arr_split as string() = context.Request.ServerVariables("HTTP_RANGE").Split("=") 'new char[] { Convert.ToChar("=") })
dim range as string = arr_split(1)
'// Make sure the client hasn't sent us a multibyte range
if (range.IndexOf(",") > -1) then
'// (?) 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 & "-" & theend & "/" & size)
throw new HttpException(416, "Requested Range Not Satisfiable")
end if
'// 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("-")) then
'// The n-number of the last bytes is requested
anotherStart = size - Convert.ToInt64(range.Substring(1))
else
arr_split = range.Split("-")
anotherStart = Convert.ToInt64(arr_split(0))
dim temp as long = 0
if (arr_split.Length > 1 andalso Int64.TryParse(arr_split(1).ToString(), temp)) then
anotherEnd = Convert.ToInt64(arr_split(1))
else
anotherEnd = size
end if
end if
'/* 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.
if (anotherEnd > theend) then
anotherEnd = theend
else
anotherEnd = anotherEnd
end if
'// Validate the requested range and return an error if it's not correct.
if (anotherStart > anotherEnd or anotherStart > size - 1 or anotherEnd >= size) then
context.Response.AddHeader("Content-Range", "bytes " + start + "-" + theend + "/" + size)
throw new HttpException(416, "Requested Range Not Satisfiable")
end if
start = anotherStart
theend = anotherEnd
length = theend - start + 1 '// Calculate new content length
fp = reader.BaseStream.Seek(start, SeekOrigin.Begin)
context.Response.StatusCode = 206
end if
end using
'// Notify the client the byte range we'll be outputting
context.Response.AddHeader("Content-Range", "bytes " & start & "-" & theend & "/" & size)
context.Response.AddHeader("Content-Length", length.ToString())
'// Start buffered download
context.Response.WriteFile(fullpath, fp, length)
context.Response.End()
end sub