Skip to content

Instantly share code, notes, and snippets.

@naartjie
Created November 14, 2022 13:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save naartjie/8cdccd800a93f55f8ccbbfc6cff35fe5 to your computer and use it in GitHub Desktop.
Save naartjie/8cdccd800a93f55f8ccbbfc6cff35fe5 to your computer and use it in GitHub Desktop.
#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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment