我正在尝试创建一个测试页面,其中包含一个HTML5 VIDEO标签,可以播放转换后的视频。我成功地将视频转换并在服务器上本地存储,但我希望能够通过另一个.aspx页面传输所有视频。
假设我有一个包含HTML代码和getvideo.aspx页面的player.aspx页面除了提供视频二进制文件之外什么都不做,我认为以下代码在我的player.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>
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 )
我在页面输出上的所有内容都是一个HTML视频播放器(chrome的基本播放器),它似乎超时并且PLAY按钮变为灰色。 Chrome开发者工具中的网络工具显示它正在下载45mb并获得200响应代码。这告诉我它工作正常。虽然我收到状态为“已取消”的第二个GET请求?
如果我访问www.mywebsite.com/output/videos/myvideo.mp4,那么这在浏览器中播放正常,因此我知道IIS配置为正确流式传输视频。
此外,如果我将响应内容处置更改为“附件”,则浏览器在转到我的ASPX页面时会正确强制下载视频,但这也无法在HTML播放器上正确播放。是否有一些“聪明”的HTML5 VIDEO标签正在阻止.aspx文件通过.net提供视频?或者我错过了回复标题?
谢谢!
答案 0 :(得分:3)
固定!
这里的问题可能与范围请求的HTML5视频实现有关。如果不在用于发送视频的页面中支持范围请求,它们将无法工作。
Scott Mitchell的这篇非常有用的帖子让我了解了这个案例: http://dotnetslackers.com/articles/aspnet/Range-Specific-Requests-in-ASP-NET.aspx
另一篇来自Chris Coulson的帖子,它提供了C#中的解决方案实现! http://blogs.visigo.com/chriscoulson/easy-handling-of-http-range-requests-in-asp-net/
我发现的代码Chris的vb.net端口如下所示,实现它只是将它放在你的页面中:
system.web.httpcontext.current.Response.ContentType = "video/" & convertFormat.toString
RangeDownload(convertedVideo, system.web.httpcontext.current)
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