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 that to a server with Http.fileBody (and I guess Http.post) …
Retrieve the URL of a successfully stored image
Store it in the model ready to add to a form
Any security concerns? (api secrets etc)
So it’d be a two-step form I guess, where you have an image upload URL that later gets attached to a Http.post stored as json. I know how to do (1) and (5) but the others are fuzzy.
Amazon S3 would be one obvious choice, but last time I checked their admin isn’t particularly user-friendly, and I’m not sure how much they’d charge for image retrieval. Here’s another affordable image server at $100 per year. The alternative is to post them and manually migrate to my own hosting.
Anyway, 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.
Helps avoid duplicate names if the filename can be randomised ↩︎
When Elm Designer was online it used Imgbb to store bitmap images (not SVG) uploaded by users of the app.
API access is free and after signup you can get a key to make calls. It is just a HTTP POST call. I consider the service quality at “demo level” but if you need to cook up something quickly I would use it.
The Elm Designer wiring code is quite complex, because the app allows you to select multiple image(s) from disk or drag&drop them, and show process for each upload. You might not need all this complexity.
Hey @passiomatic yes for now I think I prefer jQuery-style simplicity, without worrying about too many bells and whistles
So far I’ve made a few basic tests of another server (I’ve been a bit put off Imgbb due to negative reviews, but I guess you get what you pay for). It seems like you can upload local files with FILES["source"] but I can’t figure out how to do that with CURL.
As for your Imgbb module, it would be great to see some comments so I can follow it a bit better (there’s a lot of new stuff there, and I’m not sure what Http.track is doing — is that the track upload progress you’re talking about?)
Yeah your Msg has a LOT going on (with a lot of stuff I don’t understand)! From a UX perspective that’s probably nicer, but I’ve decided that to keep my learning light for now (I’m pretty much a one-man-band at the moment!), so a simple button suits me. Perhaps with a progress bar.
Fancy UI looks cool, but it seems to add a lot of overhead. I think I’m also going to have to look into breaking up a file and Msg into their own modules. There’s a lot to keep in your head there.
So TL;DR:
Is attaching a local file possible? Or must you convert it to base64?
We use S3 and native browser/Elm file upload for handling PDFs at work. On the Elm side there hasn’t been too much too do, most of the work has had to been server side with scoping files between users and the actual handling of storing/retrieving files.
@jxxcarlson might have more thoughts on images specifically as I believe he’s done some work here with his Lamdera apps.
Oh ok. Yes I definitely don’t want to deal with anything server side. I’d hire someone to do that I reckon. Any clues from @jxxcarlson would be much appreciated.
Funnily enough even with curl a base64 url string is throwing a server error[1]
@wolfadex Yup I figured that out after double checking the csv file example.
File.toUrl converts an image to a base64 url string …
However, it seems .png files are NOT converting?
I’ve sent a support message to that image hosting site, perhaps I’ll try Imgbb as well, make sure it’s not an Elm problem. Perhaps it’s due to localhost not being https?
Why don’t you send the model.image along with in your message since at the point where the message is sent you know exactly that your image isn’t a Nothing?
Thanks @wolfadex I guess I’ll wrap my head around modules as I improve. It’s probably a better idea to make sure there’s no naming conflicts with elm/... packages. For now I’m using File_.SomeModule.
Thanks for clarifying that Never. It feels a bit weird to me!
I didn’t think to do that. Do you mean Just url → onClick (SendToServer url)?
Why do you send the file name in the message instead of setting it directly on the model?
In the csv example he’s using a Task to convert to a string …
So I thought to do the same thing with the File.toUrl …
At which point (in the update) you wouldn’t be able to grab the name anymore.
Is there a better way to do this?
I think the server problem is either me doing something wrong in the url, or the server has the problem, as I’ve encoded and decoded a few base64 images and they’re not posting with curl either.
You should be fine with File.SomeModule. If anything I’d give a more accurate name instead of File. E.g. your modules seem to deal with images specifically so a more helpful name might be File.Image or ImageFile or even Image.
I also wouldn’t worry specifically about the elm/* packages. It’s more of a general issue, like if you used elm-ui 1.1.8 then you wouldn’t be able to name any of your local modules Element. I’d focus more on giving your modules names that make sense when you’re looking at the name along.
Exactly!
Which makes sense because a csv file is a specialized text file. If you open it in your text editor it’s still legible.
there’s no need to pass the name through the message+update loop again (as best I can tell).
A small stylistic opinion. I’d merge all of your File_.* modules into a single module. A module should generally be a container of sorts around a specific type. I’d also recommend Components | Elm Land for a very solid guide about how to model your component like modules.