使用 Fable-Elmish 将 React.FormEvent 转换为 BodyInit

Convert React.FormEvent to BodyInit using Fable-Elmish

我正在尝试使用 Fable-Elmish 和 React Helpers 上传文件。但是,我不知道如何将选择文件时的表单事件转换为可以使用 Fetch 发送到服务器的内容。这是观点:

R.input [
        ClassName "input-control" 
        Type "file"
        OnChange (fun x -> FileUploaded x.target |> dispatch )
    ] []

我的更新函数对应部分:

 | FileUploaded file ->
    model, Cmd.ofPromise postCsv file FetchSuccess FetchFailure

以及使用 fetch 调用 api 的函数:

let postData input =
    let formData = FormData.Create()
    formData.append("file.csv", input?files)
    let defaultProps =
        [ RequestProperties.Method HttpMethod.POST
        ; RequestProperties.Body (formData |> unbox)]
    promise {
        return! Fable.PowerPack.Fetch.fetch ("/api/data") defaultProps
    }

如何将React.FormEvent转换成fetch需要的BodyInit?

您需要创建一个新的 FormData 对象并将文件附加到它。

let formData = FormData.createNew formData.append("file", file.[0])

然后更改对 postRecord 的调用以传递 formData 而不是文件。您需要提取以对其进行编码,但您只是传递原始文件数组。

至少这是我对 fetch example 上传文件的理解。另外,post 记录在我看来不对,是否只有 "post" 方法可以使用? post记录意味着它需要一个记录类型。

我认为Fetch.postRecord是你的问题,它将Content-Type header设置为application/json,当it should be multipart/form-data.

您需要使用原始提取 API,而不是 powerpack 包装器 like this

在测试您的代码时,检查 ev.target?value 显示该事件只是获取所选文件的名称。 postRecord 似乎用于将 json 发送到端点。你将要移植: https://medium.com/ecmastack/uploading-files-with-react-js-and-node-js-e7e6b707f4ef ,到你想做的事情。

原来我没有正确使用 FileList API。这是 post 方法的工作解决方案:

let postData input =
let formData = FormData.Create()
formData.append("file.csv", input?files?item(0))
let defaultProps =
    [ RequestProperties.Method HttpMethod.POST
    ;RequestProperties.Headers [unbox EncType "multipart/form-data"]
    ; RequestProperties.Body (formData |> unbox)]
promise {
    return! Fable.PowerPack.Fetch.fetch ("/api/data") defaultProps
}