haskell - 如何使用 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
| ^^^
所以我只需要转换String -> Request
?在 http-conduit 中显然有一个功能,但它没有按预期工作 - 我仍然得到同样的错误。
我可以强制 URL 成为这样的请求:
let url = "https://www.example.com/sitemap.xml" :: Request
但是当然这会破坏我分解文件名的部分,因为它需要 a[Char]
而不是 a Request
。
所以我被困住了——如果我将 URL 设为字符串,它会破坏 http-conduit。如果我把它作为一个请求,它会破坏字符串操作。
我觉得这么简单的事情不应该这么难,不是吗?
编辑:好的,所以我几乎可以让它与这个添加一起工作:
let urlParts = B8.split '/' $ B8.pack (show url)
编译,但它使文件名损坏。试图打印出文件名给出:"1.1\n}\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 中提取的部分的更多信息,请参阅文档。
推荐阅读
- github - 存储库从 bitbucket 同步到 github 作为备份存储库
- javascript - 用于在滚动上淡化图像的 Javascript 仍在页面加载时显示图像
- database - Access 数据库未通过 Vb.net 中的文本框更新
- notifications - JBPM - 如何实现基于 DB 用户的任务通知 - JBPM 7.56.0
- typescript - 带有动态参数的 TypeScript 重用类型
- sql-server - SQL Server 2019 中的“数据”和“值”关键字是什么,它们是如何工作的?
- node.js - 如何使用模块化 Firebase v9 初始化 Firebase 管理员?
- ios - 使用 iOS Swift 动画图像以滑出视图的一侧
- networking - 通过第 2 层交换机的 VLAN 数据包
- amazon-web-services - SES listContacts:我们计算的请求签名不匹配