import Network.URI
import Network.HTTP
import Network.Browser
get :: URI -> IO String
get uri = do
let req = Request uri GET [] ""
resp <- browse $ do
setAllowRedirects True -- handle HTTP redirects
request req
return $ rspBody $ snd resp
main = do
case parseURI "http://cn.bing.com/search?q=hello" of
Nothing -> putStrLn "Invalid search"
Just uri -> do
body <- get uri
writeFile "output.txt" body
这是haskell输出和curl输出之间的差异
答案 0 :(得分:8)
在这里使用String
作为中间数据类型可能不是一个好主意,因为它会在读取HTTP响应和写入文件时引起字符转换。如果这些转换不一致,这可能会导致损坏,因为它们似乎就在这里。
由于您只想直接复制字节,因此最好使用ByteString
。我选择在这里使用惰性ByteString
,因此不必一次性加载到内存中,但可以延迟流式传输到文件中,就像使用String
一样。
import Network.URI
import Network.HTTP
import Network.Browser
import qualified Data.ByteString.Lazy as L
get :: URI -> IO L.ByteString
get uri = do
let req = Request uri GET [] L.empty
resp <- browse $ do
setAllowRedirects True -- handle HTTP redirects
request req
return $ rspBody $ snd resp
main = do
case parseURI "http://cn.bing.com/search?q=hello" of
Nothing -> putStrLn "Invalid search"
Just uri -> do
body <- get uri
L.writeFile "output.txt" body
幸运的是,Network.Browser
中的函数被重载,因此对延迟字节串的更改只涉及将请求正文更改为L.empty
,并将writeFile
替换为L.writeFile
,以及改变函数的类型签名。