11

我正在尝试使用 Network.HTTP 模块下载图像但收效甚微。

import Network.HTTP

main = do
  jpg <- get "http://www.irregularwebcomic.net/comics/irreg2557.jpg"
  writeFile "irreg2557.jpg" jpg where
       get url = simpleHTTP (getRequest url) >>= getResponseBody

输出文件出现在当前目录中,但在 chromium 或 ristretto 下无法显示。Ristretto 报告“解释 JPEG 图像文件时出错(不是 JPEG 文件:以 0c3 0xbf 开头)”。

4

1 回答 1

23
writeFile :: FilePath -> String -> IO ()

String. 那是你的问题,就在那里。String用于 unicode 文本。尝试在其中存储二进制数据将导致损坏。在这种情况下尚不清楚腐败是由simpleHTTP还是由完成的writeFile,但这最终并不重要。您使用了错误的类型,当遇到不构成有效 unicode 编码的字节时,某些东西会破坏数据。

至于解决这个问题,较新版本的HTTP返回类型是多态的,并且可以处理返回 a 中的原始字节ByteString。您只需要更改将字节写入文件的方式,这样它就不会推断出您想要一个String.

import qualified Data.ByteString as B
import Network.HTTP
import Network.URI (parseURI)

main = do
    jpg <- get "http://www.irregularwebcomic.net/comics/irreg2557.jpg"
    B.writeFile "irreg2557.jpg" jpg
  where
    get url = let uri = case parseURI url of
                          Nothing -> error $ "Invalid URI: " ++ url
                          Just u -> u in
              simpleHTTP (defaultGETRequest_ uri) >>= getResponseBody

获取多态请求的构造有点笨拙。如果问题 #1得到解决,那么使用getRequest url就足够了。

于 2012-07-17T01:28:27.600 回答