管道 http 流式传输到文件 (sinkFile) 避免在 http returns 错误时创建文件
conduit http streaming to file (sinkFile) avoid file creation when http returns error
当 http 代码不成功并且我希望 不 创建文件时,我需要从 getSrc return 获取什么值(通过 sinkFile)
如果我只是 return getResponseBody res http 错误本身被保存到文件中。
downloadURL :: String -> FilePath -> IO ()
downloadURL url location = do
request <- parseRequest url
runResourceT
$ runConduit$ httpSource request getSrc
.| sinkFile location
where
getSrc res = do
let success = statusIsSuccessful . getResponseStatus $ res
if success then
getResponseBody res
else
???
据我了解,如果响应成功,您希望将响应主体通过管道传输到某个管道,而如果响应不成功,则希望通过管道传输到备用管道。
我相信最简单的解决方案是 "choosing" 使用代码中已有的 if ... then ... else
的管道 - 类似于
module Main where
import Conduit ( printC
)
import Data.Conduit ( runConduitRes
, (.|)
, yield
)
import Data.Conduit.Binary ( sinkFile
)
import Network.HTTP.Simple ( parseRequest
, httpSource
, getResponseStatus
, getResponseBody
)
import Network.HTTP.Types.Status ( statusIsSuccessful
)
main :: IO ()
main = do
requestText <- init <$> readFile "notes/request.txt"
downloadURL requestText "notes/sink.txt"
downloadURL :: String -> FilePath -> IO ()
downloadURL url location = do
request <- parseRequest url
runConduitRes (httpSource request processResponse)
where
processResponse response =
if statusIsSuccessful (getResponseStatus response)
then (getResponseBody response) .| sinkFile location
else yield "an alternate operation" .| printC
您可以将 yield "an alternate operation" .| printC
替换为另一个满足您实际需要的管道。
请注意,现在 sinkFile location
仅在成功案例中执行,因此失败案例不会创建任何文件。
Kartin 的解决方案应该可以正常工作。您可以采用的另一种方法是使用 sinkFileCautious
而不是 sinkFile
,并在无效状态代码上抛出运行时异常。事实上,您可以将 parseRequest
替换为 parseUrlThrow
以自动获得此行为。
当 http 代码不成功并且我希望 不 创建文件时,我需要从 getSrc return 获取什么值(通过 sinkFile)
如果我只是 return getResponseBody res http 错误本身被保存到文件中。
downloadURL :: String -> FilePath -> IO ()
downloadURL url location = do
request <- parseRequest url
runResourceT
$ runConduit$ httpSource request getSrc
.| sinkFile location
where
getSrc res = do
let success = statusIsSuccessful . getResponseStatus $ res
if success then
getResponseBody res
else
???
据我了解,如果响应成功,您希望将响应主体通过管道传输到某个管道,而如果响应不成功,则希望通过管道传输到备用管道。
我相信最简单的解决方案是 "choosing" 使用代码中已有的 if ... then ... else
的管道 - 类似于
module Main where
import Conduit ( printC
)
import Data.Conduit ( runConduitRes
, (.|)
, yield
)
import Data.Conduit.Binary ( sinkFile
)
import Network.HTTP.Simple ( parseRequest
, httpSource
, getResponseStatus
, getResponseBody
)
import Network.HTTP.Types.Status ( statusIsSuccessful
)
main :: IO ()
main = do
requestText <- init <$> readFile "notes/request.txt"
downloadURL requestText "notes/sink.txt"
downloadURL :: String -> FilePath -> IO ()
downloadURL url location = do
request <- parseRequest url
runConduitRes (httpSource request processResponse)
where
processResponse response =
if statusIsSuccessful (getResponseStatus response)
then (getResponseBody response) .| sinkFile location
else yield "an alternate operation" .| printC
您可以将 yield "an alternate operation" .| printC
替换为另一个满足您实际需要的管道。
请注意,现在 sinkFile location
仅在成功案例中执行,因此失败案例不会创建任何文件。
Kartin 的解决方案应该可以正常工作。您可以采用的另一种方法是使用 sinkFileCautious
而不是 sinkFile
,并在无效状态代码上抛出运行时异常。事实上,您可以将 parseRequest
替换为 parseUrlThrow
以自动获得此行为。