2010-12-01 12 views

Antwort

4

Sie benötigen für einen Range-Header in der Request Objekt zu suchen, die auf Ihre ProcessRequest Methode übergeben Teil des HttpContext ist. Es gibt keine Range Eigenschaft in der HttpRequest Klasse, so dass Sie in der Headers suchen müssen. Wenn es eine Range ist, wird es von der Form:

Range: bytes=<start>-<end>

Wo <start> und <end> ganze Zahlen sind.

Range: bytes=32768-98304

Sie werden den Text in Zahlen zu analysieren haben und behandeln entsprechend: Zum Beispiel, 64K aus der Mitte einer Datei wollte, wenn jemand.

+0

Gute Antwort. Im Interesse zukünftiger Generationen wäre ein kleiner Beispielcode wünschenswert. Sobald ich es umgesetzt habe, hoffe ich, dass es Ihnen nichts ausmacht, wenn ich es in Ihre Antwort injiziere. – Larsenal

+0

@Larsenal: Ich habe keinen Beispielcode angegeben, weil ich keinen Code habe. Ich erinnere mich, dass ich vor einigen Jahren damit gearbeitet habe, aber der Code ist längst weg. Hoffentlich reicht meine kurze Beschreibung, um Sie zu beginnen. Es macht mir nichts aus, wenn du Code in meine Antwort eingibst. –

+0

FWIW, dies führte zu mir, um den folgenden Beitrag mit Code zu finden, der zeigt, wie man mit dem Fernantrag umgehen kann: http://blogs.visigo.com/chriscoulson/easy-handling-of-http-range-requests-in-asp- Netz/ –

3

Beachten Sie, dass die Range-Header-Syntax auch Dinge wie "0-500, 100-1500" (mehrere Bereiche) und "-500" (die letzten 500 Bytes) ermöglicht. Siehe RFC 2616 für die blutigen Details, die hier zu kurz sind.

0

Basierend auf dem Blog-Eintrag, der oben mit dem Kommentar von @ brent-keller verlinkt ist - der seinerseits auf CodePlex entry verweist - habe ich die untenstehenden Änderungen vorgenommen. Es wurde mit FDM (verfügbar here) getestet. MultiRange-Anfragen werden (noch) nicht unterstützt. No Web.config Einträge sind erforderlich.

Die ursprüngliche Methode bei CodePlex enthält einen Fehler: Der Header Accept-Ranges sollte einen Wert von bytes haben, nicht den zurückzugebenden Bytebereich. Das gehört zum Content-Range Header. Der Download funktioniert immer noch, aber Sie erhalten nicht byte serving, wenn Sie diesen Fehler machen.

Diese modifizierte Version wurde aus Gründen der Kürze und Lesbarkeit überarbeitet. Es hat auch den Vorteil, dass die zurückgegebene Datei nicht notwendigerweise an die tatsächliche URL gebunden ist - tatsächlich kann der Handler direkt vom Browser und gegebenenfalls mit Abfragezeichenfolgenargumenten aufgerufen werden. Dies ermöglicht die dynamische Datei-/Datenerstellung und -antwort.

Hoffentlich kann jemand etwas damit anfangen.

HTTP Handler

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 

Bereich anfordern

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 

Bereich Reaktions

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