Skip to content

Instantly share code, notes, and snippets.

@ozanmakes
Created November 19, 2014 15:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save ozanmakes/f0dcea018fb72ebed3e0 to your computer and use it in GitHub Desktop.
Save ozanmakes/f0dcea018fb72ebed3e0 to your computer and use it in GitHub Desktop.
http-conduit downloader
{-# LANGUAGE OverloadedStrings #-}
module Downloader where
import Control.Monad.IO.Class (liftIO)
import Control.Monad.Trans.Resource
import qualified Data.ByteString as BS
import qualified Data.ByteString.Char8 as C8
import Data.Conduit
import qualified Data.Conduit.Binary as CB
import Network.HTTP.Conduit
contentLength :: Response body -> Integer
contentLength = read . C8.unpack . snd . head .
filter ((== "Content-Length") . fst) . responseHeaders
reportProgress :: Integer -> (Double -> IO ()) ->
ConduitM BS.ByteString o (ResourceT IO) ()
reportProgress total updater =
loop 0
where
loop len = await >>= maybe (return ()) (\bs -> do
let currentBlocks = len + BS.length bs
let percentage = fromIntegral (currentBlocks * 100) /
fromIntegral total
liftIO $ updater percentage
loop currentBlocks)
downloadFile :: String -> FilePath -> (Double -> IO ()) -> IO ()
downloadFile url name updater = withManager $ \manager -> do
req <- parseUrl url
let req' = req { requestHeaders = [("User-Agent", "wget/1.15")]}
res <- http req' manager
responseBody res $$+-
CB.conduitFile name =$=
reportProgress (contentLength res) updater
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment