web-services – 如何使用Yesod和Http-Conduit将FileInfo发布到Web服务?

我正在使用默认的Yesod脚手架项目.

我创建了一个显示上传文件的简单表单的页面.

(该表单可能会使用
Javascript在客户端上创建.)

为简洁起见,表单只有一个文件输入:

<form method="post" action=@{UploadR}>
   <input type="file" name="myfile">
   <button type="submit">

我的目标是处理表单数据,然后将文件上传到Web服务.
我处理表单没有问题,我担心的是与Web服务进行交互.
例如,给定以下Yesod处理程序:

postUploadR :: Handler Html
postUploadR = do
    mgr <- fmap httpManager getYesod
    fi  <- runInputPost $ireq fileField "myfile"
    let fSource = fileSource fi
        fName   = fileName fi
    req <- parseUrl "http://webservice/upload"
    let areq = req { method = methodPost
                   , requestBody = requestBodySourceChunked fSource
                   }
    res <- httpLbs areq mgr
    defaultLayout $do
      setTitle "file uploaded"
      [whamlet|
       <h3> Success
       <p> You uploaded #{fName}.
      |]

webservice返回错误:fail post content-length,但其他所有内容都按预期工作.也许服务器不支持分块请求体?

最佳答案 我认为你对chunked request body的猜测是正确的.你需要做的是:

>将上传的内容流式传输到临时文件中.
>获取该文件的大小.
>使用requestBodySource并提供文件长度及其内容.

幸运的是,sinkCacheLength功能可以很容易地处理步骤(1)和(2).你最终会得到类似的东西:

(fSize, fSource) <- fileSource fi $$sinkCacheLength
点赞