如何使用Haskell从Internet下载文件?

我只是想做一些类似于wget从 Internet 下载文件的操作。我看到曾经有一个名为http-wget的包,但它已被弃用,取而代之的是 http-conduit。

Http-conduit 有一个简单的例子来说明如何使用httpBS. 所以接下来,我得到了这个工作:

{-# LANGUAGE OverloadedStrings #-}

import Network.HTTP.Simple
import qualified Data.ByteString.Char8 as B8

main :: IO ()
main = do
  let url = "https://www.example.com/sitemap.xml"
  resp <- httpBS url
  B8.putStrLn $ getResponseBody resp

这适用于从 URL 获取文件名 (sitemap.xml):

{-# LANGUAGE OverloadedStrings #-}

import Network.HTTP.Simple
import qualified Data.ByteString.Char8 as B8

main :: IO ()
main = do
  let url = "https://www.example.com/sitemap.xml"
  let urlParts = B8.split '/' $ B8.pack url
  let fileName = Prelude.last urlParts
  B8.putStrLn fileName

但我不能把它们放在一起:

{-# LANGUAGE OverloadedStrings #-}

import Network.HTTP.Simple
import qualified Data.ByteString.Char8 as B8

main :: IO ()
main = do
  let url = "https://www.example.com/sitemap.xml"
  let urlParts = B8.split '/' $ B8.pack url
  let fileName = Prelude.last urlParts
  resp <- httpBS url
  B8.putStrLn $ getResponseBody resp

这给出了错误:

ny1920-parse.hs:12:41: error:
    • Couldn't match type ‘Request’ with ‘[Char]’
      Expected type: String
        Actual type: Request
    • In the first argument of ‘B8.pack’, namely ‘url’
      In the second argument of ‘($)’, namely ‘B8.pack url’
      In the expression: B8.split '/' $ B8.pack url
   |
12 |   let urlParts = B8.split '/' $ B8.pack url
   |                                         ^^^

ny1920-parse.hs:12:41: error:
    • Couldn't match type ‘Request’ with ‘[Char]’
      Expected type: String
        Actual type: Request
    • In the first argument of ‘B8.pack’, namely ‘url’
      In the second argument of ‘($)’, namely ‘B8.pack url’
      In the expression: B8.split '/' $ B8.pack url
   |
12 |   let urlParts = B8.split '/' $ B8.pack url
   |                                         ^^^

所以我只需要转换String -> Request?在 http-conduit 中显然有一个函数,但它没有按预期工作 - 我仍然遇到相同的错误。

我可以强制 URL 是这样的请求:

但是当然这会破坏我分解文件名的部分,因为它需要 a[Char]而不是Request.

所以我被卡住了——如果我把 URL 设为字符串,它会破坏 http 管道。如果我让它成为一个请求,它会破坏字符串操作。

我觉得这么简单的事情不应该这么难,不是吗?

编辑:好的,所以我几乎可以让它与这个添加一起工作:

  let url = "https://www.example.com/sitemap.xml" :: Request

编译,但它使文件名损坏。试图打印出文件名给出:"1.1n}n"而不是sitemap.xml.

回答

我将不同意这里的另一个答案:分裂/自己是一个坏主意。不要试图实现一个特别的 URL 解析器;这比你想象的要困难得多。相反,重新使用您已经拥有的解析:

{-# LANGUAGE OverloadedStrings #-}

import Network.HTTP.Client
import Network.HTTP.Simple
import Network.URI
import qualified Data.ByteString.Char8 as B8

main :: IO ()
main = do
    let request = "https://www.example.com/sitemap.xml"
        fileName = Prelude.last . pathSegments . getUri $ request
    resp <- httpBS request
    B8.putStrLn $ getResponseBody resp

有关可以从 URI 中提取的部分的更多信息,请参阅文档。


以上是如何使用Haskell从Internet下载文件?的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>