Вероятно, здесь не рекомендуется использовать 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
, а также изменение сигнатуры типа функции.