Skip to content

Instantly share code, notes, and snippets.

@naartjie
Created November 14, 2022 13:33
Show Gist options
  • Save naartjie/8cdccd800a93f55f8ccbbfc6cff35fe5 to your computer and use it in GitHub Desktop.
Save naartjie/8cdccd800a93f55f8ccbbfc6cff35fe5 to your computer and use it in GitHub Desktop.

Revisions

  1. naartjie created this gist Nov 14, 2022.
    59 changes: 59 additions & 0 deletions get.fsx
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,59 @@
    #r "nuget: FsHttp, 9.1.2"

    open FsHttp
    open System

    let getSize url =
    async {
    let! r =
    http {
    HEAD url
    CacheControl "no-cache"
    }
    |> Request.sendAsync

    return float r.content.Headers.ContentLength.Value
    }

    let sizeToRanges (size: float) =
    let x = Math.Ceiling(size / (float 5))

    seq { 1. .. 5. }
    |> Seq.map (fun n -> x * (n - 1.), (min size (x * n - 1.)))
    |> Seq.toList

    let getRange url x1 x2 =
    async {
    let! res =
    http {
    GET url

    (* https://developer.mozilla.org/en-US/docs/Web/HTTP/Range_requests *)
    header "range" $"bytes={x1}-{x2}"

    CacheControl "no-cache"
    }
    |> Request.sendAsync

    let! bytes = Response.toBytesAsync res
    return bytes
    }


    let download url dest =
    let size = getSize url |> Async.RunSynchronously
    printfn $"url={url} size={size}"

    let content =
    sizeToRanges size
    |> List.map (fun (x1, x2) -> getRange url x1 x2)
    |> fun content -> Async.Parallel(content, maxDegreeOfParallelism = 5)
    |> Async.RunSynchronously
    |> Array.concat

    IO.File.WriteAllBytes(dest, content)
    printfn $"got {url}, size={content.Length}"

    let args = Environment.GetCommandLineArgs()
    let url, dest = args.[2], args.[3]
    download url dest