File Upload in Elm

断了今生、忘了曾经 提交于 2019-11-28 09:45:12
Simon H

I am the author of the library MisterMetaphor refers to. It's easier to use than he explains though. Take a look at how I set up elm-package.json in the example: https://github.com/simonh1000/file-reader/blob/master/example/elm-package.json - just add "native-modules": true,.

I have written a blog to support the release of the code for 0.18 and show how uploads to e.g. S3 can be done in Elm.

The official way to do it is now https://package.elm-lang.org/packages/elm/file/latest/

This is an addition that came in Elm 0.19.

Now the official Http package supports it as well. Here is an example from https://package.elm-lang.org/packages/elm/http/latest/Http#request

import File
import Http

type Msg = Uploaded (Result Http.Error ())

upload : File.File -> Cmd Msg
upload file =
  Http.request
    { method = "PUT"
    , headers = []
    , url = "https://example.com/publish"
    , body = Http.fileBody file
    , expect = Http.expectWhatever Uploaded
    , timeout = Nothing
    , tracker = Nothing
    }
MisterMetaphor

Use a library like file-reader.

There is a set of pretty comprehensive examples, you can start with this one.

There's a caveat, though. Since this library uses some native code, you can't get it from the official package repo. So you will have to resort to manually installing it.

For this purpose, I wrote this hacky elm-package install replacement. It expects an exact-dependencies.json file in the root directory of your project. You can get this file initially from the elm-stuff directory that elm-package creates when building your project. You then add a reference to the file-reader package to the exact-dependencies.json file like this:

{
    "evancz/elm-effects": "2.0.1",
    "evancz/virtual-dom": "2.1.0",
    "evancz/elm-http": "3.0.0",
    "evancz/start-app": "2.0.2",
    "evancz/elm-html": "4.0.2",
    "elm-lang/core": "3.0.0",
    "simonh1000/file-reader": "1.0.0"
}

You will also need to add a reference to file-reader to your elm-package.json file:

{
    "version": "1.0.0",
    "summary": "helpful summary of your project, less than 80 characters",
    "repository": "https://github.com/user/project.git",
    "license": "BSD3",
    "source-directories": [
        "."
    ],
    "exposed-modules": [],
    "dependencies": {
        "elm-lang/core": "3.0.0 <= v < 4.0.0",
        "evancz/elm-effects": "2.0.1 <= v < 3.0.0",
        "evancz/elm-html": "4.0.2 <= v < 5.0.0",
        "evancz/elm-http": "3.0.0 <= v < 4.0.0",
        "evancz/start-app": "2.0.2 <= v < 3.0.0",
        "simonh1000/file-reader": "1.0.0 <= v < 2.0.0",
    },
    "elm-version": "0.16.0 <= v < 0.17.0"
}

After this, you run the elm-package install replacement and hopefully it will work.

The other option to handle file uploads in Elm is to

  • get a base64-encoded value from the FileReader into your Elm app through a port.
  • Then, send that base64-encoded value to your server (e.g. in a JSON body).

A tutorial can be found here https://www.paramander.com/blog/using-ports-to-deal-with-files-in-elm-0-17 (it says it's for Elm 0.17, but it works unchanged in Elm 0.18).

The downsides of this approach are

  • your server needs to base64-decode the files it receives which increases server load a little, and
  • base64-encoding increases the amount of bytes that will go over the wire (compared to a file/blob).

The upside:

  • no need to use a package with native code.

From the Elm Http docs: "Right now it only supports strings, but we will support blobs and files when we get an API for them in Elm."

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!