wai дает нам функцию responseStream
а>
responseStream :: Status -> ResponseHeaders -> StreamingBody -> Response
который создает Response
из StreamingBody
, что на самом деле является функцией
type StreamingBody = (Builder -> IO ()) -> IO () -> IO ()
что, учитывая действие записи и действие сброса, находит где-то несколько байтов и выполняет всю запись и сброс.
wai также предоставляет нам готовый файл responseFile
функция:
responseFile :: Status -> ResponseHeaders -> FilePath -> Maybe FilePart -> Response
но он не удаляет файл в конце. Можем ли мы его как-то изменить? Кажется, что мы можем, с помощью responseToStream вспомогательная функция
responseToStream :: Response -> (Status, ResponseHeaders, (StreamingBody -> IO a) -> IO a)
это открывает уже построенный Response
, позволяя нам настраивать вещи.
Как это:
import Network.Wai
import Network.HTTP.Types.Status (status200)
import System.Directory (removeFile)
responseFileDeleting' :: FilePath -> Response
responseFileDeleting' filepath =
let (status,header,streamer) =
responseToStream $ responseFile status200 [] filepath Nothing
in responseStream status header (\write flush ->
-- this would be a good place to put a bracket, if needed
do streamer (\body -> body write flush)
removeFile filepath)
(Примечание: тип streamer
немного сбивает с толку из-за всего этого более высокого порядка.)
Недостатком этого решения является то, что запросы должны ждать, пока файл не будет удален для завершения. Другим вариантом может быть отправка путей к файлам в какой-то параллельная очередь, выполняющая удаление в другом потоке .
person
danidiaz
schedule
08.08.2020