2010-12-01 10 views

答えて

4

ProcessRequestメソッドに渡されたHttpContextの一部であるRequestオブジェクトのRangeヘッダーを検索する必要があります。 HttpRequestクラスにはRangeというプロパティがありませんので、Headersを参照する必要があります。 Rangeがあれば、それは次の形式になります:

<start><end>は整数で

Range: bytes=<start>-<end>

。例えば、誰かがファイルの途中から64Kを望んでいた場合:

Range: bytes=32768-98304

あなたは数字にテキストを解析し、それに応じて処理する必要があります。

+0

良い答え。将来の世代のために、少しサンプルコードがいいでしょう。私がそれを実装すると、私はあなたの答えにそれを注入するかどうか気にしないことを願っています。 – Larsenal

+0

@Larsenal:私はサンプルコードを提供しませんでした。私は数年前にこれを使って作業したことを覚えていますが、コードは長くなくなっています。うまくいけば私の短い説明はあなたを始めるのに十分です。私はあなたが私の答えにコードを注入するかどうか気にしない。 –

+0

FWIW、これは私に、遠隔地の要求を処理する方法を示すコードで次の記事を見つけることにつながります:http://blogs.visigo.com/chriscoulson/easy-handling-of-http-range-requests-in-asp-ネット/ –

3

Rangeヘッダー構文では、「0-500,100-1500」(複数の範囲)、「-500」(最後の500バイト)なども使用できます。詳細については、RFC 2616を参照してください。ここでは引用するには時間がかかりすぎます。

0

@ brent-kellerのコメントの上にリンクされたブログの投稿に基づいています。これは、CodePlex entryを参照しています。私は以下の編集を思いつきました。それはFDM(利用可能here)でテストされています。マルチレンジリクエストはサポートされていません(まだ)。 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 
関連する問題