Downloader Async Stable

open System
open System.IO
open Microsoft.WindowsAPICodePack.Dialogs
open System.Net

let (|>>) x f = f x; x

module IO =
    let rec Input _ =
        match Console.ReadLine().Trim() with
        | s when s <> "" -> s::Input()
        | _ -> []

    let DirectoryPick _ =
        let dialog = new CommonOpenFileDialog()
        dialog.IsFolderPicker <- true
        match dialog.ShowDialog() with
        | CommonFileDialogResult.Ok -> dialog.FileName
        | _ -> failwith "Empty Path"

module Log =
    open System.Threading

    type Level =
        | Log
        | Error
        | Info

    type Type =
        | ConsoleType of ConsoleColor
        | FileType of string

    let output =
        let lockObj = obj()
        fun logType level (s:string) ->
            lock lockObj (fun _ ->
                let msg = 
                    match level with
                    | Log -> "[*] "
                    | Error -> "[!] "
                    | Info -> "[i] "
                    + s
                match logType with
                | ConsoleType(c) ->
                    Console.ForegroundColor <- c
                    Console.WriteLine msg
                | FileType(p) ->
                    use log = new StreamWriter(p, true)
                    log.WriteLine msg)

    let Log = output (ConsoleType ConsoleColor.White) Log
    let Error = output (ConsoleType ConsoleColor.Red) Error
    let Info = output (ConsoleType ConsoleColor.DarkGray) Info
    let File path = output (FileType path)
    let LogAsync msg = (new Thread(fun () -> Log msg)).Start()
    let ErrorAsync msg = (new Thread(fun () -> Error msg)).Start()
    let InfoAsync msg = (new Thread(fun () -> Info msg)).Start()
    let FileAsync path level msg = (new Thread(fun () -> File path level msg)).Start()
    
let DownloadAsync path lst =
    let tempPath = path + "\\" + "temp"
    Directory.CreateDirectory tempPath |> ignore
    let logPath = path + "\\" + "Error.log"
    lst
    |> Seq.ofList
    |> Seq.map (fun url ->
        async{
            let filename = (Path.GetFileName url).Split('?').[0]
            let downloadPath = path + "\\" + filename
            let tempDownloadPath = tempPath + "\\" + filename
            if not <| File.Exists downloadPath then
                try
                    use wc = new WebClient()
                    wc.DownloadFile(Uri(url), tempDownloadPath)
                    File.Move(tempDownloadPath,downloadPath)
                    url + " -> " + filename + " done." |> Log.InfoAsync
                with 
                | e ->
                    url + " " + e.Message |>> Log.Error |> Log.FileAsync (logPath) Log.Level.Error
        })
    |> Async.Parallel
    |> Async.RunSynchronously
    |> ignore

[<STAThread>]
[<EntryPoint>]
let main argv =
    match argv.Length with
    | 0 -> DownloadAsync (IO.DirectoryPick()) (IO.Input())
    | _ -> 
        use sr = new StreamReader(argv.[1])
        sr.ReadToEnd().Split('\n')
        |> List.ofArray
        |> DownloadAsync argv.[0]
    Log.LogAsync "done."
    Console.ReadLine() |> ignore
    0

 

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注