我有一个HttpHandler将对传入的请求进行一些检查,并在某些情况下执行某些功能。需要检查的其中一个条件是请求是否为byte-range request。这是如何完成的?在.NET中检测字节范围请求HttpHandler
3
A
回答
4
你需要寻找在Request
对象是这样的HttpContext
传递给ProcessRequest
方法的一部分Range
头。 HttpRequest
类中没有Range
属性,因此您必须查看Headers
。如果有一个Range
它会是这样的形式:
Range: bytes=<start>-<end>
凡<start>
和<end>
是整数。例如,如果某人从文件的中间想64K:
Range: bytes=32768-98304
你必须分析文本转换为数字和相应的处理。
3
请注意,Range标头语法还允许诸如“0-500,100-1500”(多个范围)和“-500”(最后500个字节)之类的内容。有关血腥详细信息,请参阅RFC 2616,这些内容太长而无法引用。
0
基于在@ brent-keller评论中链接到上面的博客帖子,该博客帖子又引用CodePlex entry -I提出了下面的编辑。它使用FDM进行测试(可用here)。 MultiRange请求不支持(还)。否需要Web.config
条目。
CodePlex中的原始方法包含错误 - Accept-Ranges
标头的值应该是bytes
,而不是要返回的字节范围。这属于Content-Range
标题。下载仍然有效,但如果你犯了这个错误,你将不会得到byte serving。
为了简洁和易读,此修改后的版本进行了重构。它还有一个好处,即返回的文件不一定与实际的URL绑定在一起 - 事实上,可以直接从浏览器调用处理程序,如果需要的话可以使用查询字符串参数。这使动态文件/数据创建和响应成为可能。
希望有人可以用它做一些好事。
HTTP处理程序
Public Class Upload
Implements IHttpHandler
Public Sub ProcessRequest(Context As HttpContext) Implements IHttpHandler.ProcessRequest
Dim oFile As FileInfo
oFile = New FileInfo(Context.Server.MapPath("~/0HCJ0LE.zip"))
Me.UploadRange(Context, oFile)
End Sub
Public ReadOnly Property IsReusable() As Boolean Implements IHttpHandler.IsReusable
Get
Return False
End Get
End Property
Private Sub UploadRange(Context As HttpContext, File As FileInfo)
Dim oResponse As Response
Dim oRequest As Request
Dim _
nOffset,
nLength As Long
Using oReader As New StreamReader(File.FullName)
Context.Response.AddHeader("Accept-Ranges", "bytes")
oResponse = New Response(oReader)
oRequest = New Request(oResponse, Context)
If oRequest.HasRange Then
If oRequest.IsMultiRange Then
' At the moment we only support single ranges.'
' * Multiple range support requires some more work'
' * to comply with the specifications: http://www.w3.org/Protocols/rfc2616/rfc2616-sec19.html#sec19.2'
' *'
' * Multirange content must be sent with multipart/byteranges mediatype,'
' * (mediatype = mimetype)'
' * as well as a boundary header to indicate the various chunks of data.'
' '
' (?) Shoud this be issued here, or should the first'
' range be used? Or should the header be ignored and'
' we output the whole content?'
Me.ThrowBadRange(Context, oResponse)
Else
If oRequest.IsBadRange Then
Me.ThrowBadRange(Context, oResponse)
Else
Context.Response.StatusCode = 206
oResponse.Start = oRequest.Start
oResponse.End = oRequest.End
nOffset = oReader.BaseStream.Seek(oResponse.Start, SeekOrigin.Begin)
nLength = oResponse.End - oResponse.Start + 1
End If
End If
Else
nOffset = 0
nLength = oResponse.Size
End If
End Using
Context.Response.ContentType = MediaTypeNames.Application.Zip
Context.Response.AddHeader("Content-Disposition", $"attachment; filename={File.Name}")
Context.Response.AddHeader("Content-Length", nLength)
Context.Response.AddHeader(oResponse.HeaderName, oResponse.HeaderValue)
Context.Response.WriteFile(File.FullName, nOffset, nLength)
Context.Response.End()
End Sub
Private Sub ThrowBadRange(Context As HttpContext, Response As Response)
Context.Response.AddHeader(Response.HeaderName, Response.HeaderValue)
Throw New HttpException(416, "Requested range not satisfiable")
End Sub
End Class
范围请求
Friend NotInheritable Class Request
Public Sub New(Response As Response, Context As HttpContext)
Me.Response = Response
Me.Context = Context
End Sub
Public ReadOnly Property Start As Long
Get
If Me.Range(0) = String.Empty Then
Start = Me.Response.Size - Me.Range(1)
Else
Start = Me.Range(0)
End If
End Get
End Property
Public ReadOnly Property [End] As Long
Get
If Me.Range(0) = String.Empty Then
[End] = Me.Response.End
Else
If Long.TryParse(Me.Range(1), 0) Then
[End] = Me.Range(1)
Else
[End] = Me.Response.Size
End If
End If
[End] = Math.Min(Me.Response.End, [End])
End Get
End Property
Public ReadOnly Property HasRange As Boolean
Get
Return String.IsNullOrEmpty(Me.Context.Request.ServerVariables(HTTP_RANGE)) = False
End Get
End Property
Public ReadOnly Property IsMultiRange As Boolean
Get
Return Me.Context.Request.ServerVariables(HTTP_RANGE).Contains(",")
End Get
End Property
Public ReadOnly Property IsBadRange As Boolean
Get
Return Me.Start > Me.End OrElse Me.Start > Me.Response.Size - 1 OrElse Me.End >= Me.Response.Size
End Get
End Property
Private ReadOnly Property Range As List(Of String)
Get
Return Me.Context.Request.ServerVariables(HTTP_RANGE).Split("=")(1).Split("-").ToList
End Get
End Property
Private ReadOnly Response As Response
Private ReadOnly Context As HttpContext
Private Const HTTP_RANGE As String = "HTTP_RANGE"
End Class
范围响应
Friend NotInheritable Class Response
Public Sub New(Reader As StreamReader)
_Size = Reader.BaseStream.Length
Me.End = Me.Size - 1
End Sub
Public Property Start As Long
Public Property [End] As Long
Public ReadOnly Property Size As Long
Public ReadOnly Property HeaderName As String
Get
Return "Content-Range"
End Get
End Property
Public ReadOnly Property HeaderValue() As String
Get
Return $"bytes {Me.Start}-{Me.End}/{Me.Size}"
End Get
End Property
End Class
相关问题
- 1. XMLHTTPRequest的字节范围请求
- 2. 206部分请求 - 重叠字节的单范围请求
- 3. 如何在IIS中启用字节范围http请求
- 4. 字节范围不在HTML5音频的请求标头中
- 5. 在PHP中检测Unicode字符范围
- 6. JSF中的请求范围
- 7. 在Log4J的请求范围
- 8. 如何识别字节范围请求中最后一组字节的范围(内容 - 长度)?
- 9. 通过HTTP范围请求快速检测GIF尺寸
- 10. .NET如何测量请求中分配的字节数?
- 11. 亚马逊S3多个字节范围请求
- 12. 最后一个字节的HTTP范围请求
- 13. AFNetworking:按字节范围下载请求(即:仅文件头)
- 14. SharePoint 2010/IIS 7.5字节范围请求响应整个文件
- 15. 从没有OPTIONS请求的s3获取字节范围
- 16. 字节服务(范围请求)工作流
- 17. 创建字节范围(请求部分数据非常有用)
- 18. 使用cURL处理字节范围请求
- 19. 检测节点js中的请求字符集
- 20. JSF请求范围形式
- 21. 范围请求cxf jaxrs
- 22. Spring Rest Web请求范围
- 23. OAuth2请求其他范围
- 24. 弹簧请求范围bean
- 25. 范围内的HTTP请求
- 26. 在asp.net中的异步web请求httphandler
- 27. masm字节范围
- 28. Java泛型,检测超出范围字节
- 29. 检测一个HttpHandler
- 30. 检测ajax请求到正常请求节点js
很好的回答。为了后代,一些示例代码会很好。一旦我实现它,我希望你不介意我是否将它注入到答案中。 – Larsenal 2010-12-02 01:42:14