I was a bit surprised to learn that Elm didn’t have a way to write images to some dedicated folder, but file upload seems reasonably easy (although I’m not sure how you’d handle errors).
What I’m looking for is anyone who’s successfully used native code to:
- Upload an image,
Rename the file (which a lot of image upload sites do)[1]- Post to the server with
Http.post
orHttp.request
, - The server renames the file to a random name and returns
json
, - Retrieve the URL of a successfully stored image (and any metadata),
- Store the URL in the model, ready to add to a form.
So it’s a two-step form: Upload the image, send to the server. There are a few image servers that we could look at:
- ImgBB (low-cost, limited customer service)
FreeImage.host(poor customer service, CORS errors)- Cloudinary (untested, has Ai tools)
- Cloudflare Images (I can only find a handful of tutorials for API)
- Scripta by @jxxcarlson (useful if you’re an admin uploading images)
- Amazon S3 (I find Amazon not very user-friendly)
Right now ImageBB or CloudFront are possibly the cheapest, and you can start using them for free. I’m not sure how reliable ImageBB is, so I’d back up all your images. The alternative is to have a server-side image upload and use ports and flags, I guess.
It seems like quite an essential feature of any app to upload files, so I’m wondering how people are handling it currently. I’m not much a fan of ports, but if it’s simple to understand that’s another option.
I’ve seen a few posts on the topic, but some seem outdated or a bit complex.
The solution
Thanks to @wolfadex @passiomatic @jxxcarlson @Laurent
Dealing with images at such a low-level is new to me, so there was a lot of information to sift through, which I’ve written documentation about here (base64
, multipart, cross-origin, etc). Depending on your perspective, this should be easier to do in Elm with packages or frameworks in future.[2]
- A working ImgBB implementation with
Http.request
andHttp.stringPart
- It uses MultiPart and the equivalent of Curl
--form
- Here’s how a successful response looks
- It uses MultiPart and the equivalent of Curl
- A URL
POST
implementation that should work (but FreeImage.host has CORS errors) — any other image server that acceptsimage=<data-string>
post should work.
Both these options should cover image servers, with variations.
Other notes
@wolfadex suggests to follow this components guide when implementing within a form. Also take care of naming your modules.
You’ll also need to wrap your head around Task
which is something that can Never
fail. You’ll probably want to upload multiple images so Task.sequence
seems the way forward. As for UI you might like to track the progress of the upload.
All that is probably going to need a tutorial — there’s quite a lot of gaps in the documentation/examples for getting these things done. If you’re like me, you’d prefer higher-level detail than lower-level implementations. Hopefully there’ll be more off-the-shelf solutions in future.
Security concerns?
The only security concerns I can think of right now is exposing the API key. Uglifying your javascript may go some way to solving this, but I guess the better way would be storing it in backend code somehow.