我有一個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