Stream entire file via conduit

Viewed 85

I am struggling to download a (dynamic) file via Servant.

Say I have the following function for pulling files from S3, using this library: https://hackage.haskell.org/package/aws:

getS3Object
  :: MonadIO m
  => MonadReader Config m
  => MonadError CustomError m
  => Text
  -> m (Maybe ByteString)

getS3Object fileName = do
    config <- ask
    configObject <- constructS3Authentication
    mgr <- liftIO $ newManager tlsManagerSettings
    liftIO $ runResourceT $
      Aws.pureAws (awsConfig configObject) (s3Config configObject) mgr (S3.getObject (config ^. awsCustomerDocumentsBucket) fileName) >>= 
        \gor -> runConduit (responseBody (S3.gorResponse gor) .| await)

I then call this like so:

fetchDocument
  :: MonadIO m
  => MonadCatch m
  => MonadReader Config m
  => MonadError CustomError m
  => NewDocumentInput
  -> m ByteString

fetchDocument inputDocument = do
    let fileName = computeFileName inputDocument
    documentObject <- getS3Object fileName
    case documentObject of
      Nothing -> throwError $ OtherAWSError "No document returned, or other uncaught exception"
      Just document -> liftIO $ do    
        writeFile "./tmp/potato.pdf" document
        return document

When I call this functionality (by calling the requisite route via Postman), Potato.pdf is a 4kb file which seems like it might be a part of my PDF file but not all of it. This file can not be opened.

Oddly enough, when I change the last line of getS3Object to:

\gor -> runConduit (responseBody (S3.gorResponse gor) .| sinkFile "./tmp/foo.pdf" .| await)

the file that gets output to disk is the full correct (33KB) PDF file (whichc can be opened).

My question is, where am I losing the remainder of the file? Am I using Conduit incorrectly somehow? And how can I fix this issue.

0 Answers
Related