首页 > 解决方案 > 使用 Elm 从 POST 请求中下载文件

问题描述

我的位置是我有一个/render返回 PDF 文档的 HTTP POST 端点,并希望向用户显示一个按钮/链接,这将导致该文档被下载并保存到文件中,而无需离开我的 Elm应用程序。

理想情况下,POST 将接受text/plain具有自定义格式的正文,但我可以重新设计端点以接受multipart/form-dataapplication/x-www-form-urlencoded.

我可以按如下方式成功地将原始数据下载到 Elm 应用程序,但我不知道如何将文件保存到磁盘。

import Http

render : String -> Http.Request String
render body =
  Http.request
    { method = "POST"
    , headers = []
    , url = "/render"
    , body = Http.stringBody "text/plain" body
    , expect = expectString
    , timeout = Nothing
    , withCredentials = False
    }

标签: postdownloadelm

解决方案


我使用expectBytes而不是这样做,expectString 所以我的代码是

import Bytes exposing (Bytes)
import File.Download as Download

Msg = .. | FormUploaded (Result Http.Error Bytes)

Http.post
        { url = "/passports"
        , body =
            Http.multipartBody...
        , expect = Http.expectBytesResponse FormUploaded (resolve Ok)
        }


downloadPdf : Bytes -> Cmd msg
downloadPdf pdfContent =
    Download.bytes "form.pdf" "application/pdf" pdfContent

update : Msg -> Model -> ( Model, Cmd Msg )
update model =
...
    FormUploaded (Ok response) ->
            ( model, downloadPdf response )
    FormUploaded (Err err) ->
            ( model, Cmd.none )

-- this helper function copied from https://github.com/elm/http/blob/2.0.0/src/Http.elm#L514-L521
resolve : (body -> Result String a) -> Http.Response body -> Result Http.Error a
resolve toResult response =
    case response of
        BadUrl_ url ->
            Err (BadUrl url)

        Timeout_ ->
            Err Timeout

        NetworkError_ ->
            Err NetworkError

        BadStatus_ metadata _ ->
            Err (BadStatus metadata.statusCode)

        GoodStatus_ _ body ->
            Result.mapError BadBody (toResult body)

这并不理想,但有效

PS:我从 Elm Slack 频道获得了帮助https://elmlang.slack.com/


推荐阅读