How can one upload files using Elm? (digging the old grave)

Hi,

I’m trying to upload some files. While browsing the topics here I found the previous discussion

I couldn’t replay in the original post, hence creating a new thread here to know if there is any native solutions available other than the JS port options discussed already.

I have an example implementation

But the problem with this approach is when I click the submit button, page redirects to the storage server route. In my case it is localhost:4000/v1/upload which is handled by go application which is not desired.

Is there any way to make it not to get re-routed to the server url? Or is there any new approach people have come up with?

Any thoughts and inputs are welcome!

Best,
Santman

That is an old topic that was made obsolete by the release of elm/file. You have in that library examples for how to do various things.

2 Likes

Thank you @pdamoc. I will have a look at how to use it. At least that post got a clouser now :slight_smile:

Hi,

Just a follow up on this topic. I got the basic upload functionality working with the elm/file package. Hopefully it will be helpful for someone .

I do have some problems.

  1. It works consistently well for the text files. How ever it doesn’t work well for images or pdf files. :thinking:
  2. I get the error multipart: NextPart: EOF on the server side. I did do some googling around on the cause of such issue, but many answers are overly convolved and couldn’t get it working for the file types.
    My gut feeling is I need to update the MIME type of the response to “image/jpg” or “image/png” I’m not sure how to do it with Elm. Any inputs on this will be helpful.

Check out this article by Evan. I came across it a few days ago while needing to refresh on uploading images. There’s some good examples which might help solve your problem.

I ended up sending the base64 string of the image (after being resized and cropped by JS) over a websocket, and I don’t ever use the http protocol, always prefer ws, so can’t help you directly.

If Evans article and examples don’t help, I’m sure someone round here will.

Thank you @paulh for your response. And sharing the article. Yes it was helpful.

Can you please share some sample code how you use ws to send image or pdf files. I would love to learn that technique.

Best,
Santman

1 Like

Here are some more updates on the experiments I did

Testing with Curl

I used the following command to test the end point. When I use Curl I could consistently able to upload any type of file (png/jpeg/pdf/text/html etc)

100 % of files were transmitted and received at the server.

#!/bin/bash


curl -i -X POST -H "Content-Type: multipart/form-data" -F "myFile=@$1" http://localhost:4000/v1/upload

Testing with Elm app (Elm land)

Here again I never had any issues with the text files. But the image files were some times sent and failed most of the time. Even I could send couple of pdf files intially

Text files 100% Success rate
Image files 10 to 20 % success rate
PDF files 5 to 10% success rate.

I used same set of files for Curl and Elm app.

With this experiment I could conclude that there is something going wrong from the Elm app side. Any further inputs on how could this be debugged can be helpful.

Hoy!

Since you send multiple files, you should name your file part with []

-            nameFiles "myFile" options.files
+            nameFiles "myFile[]" options.files

ERR:

I just read the go code: you should use fileBody instead of filePart Http - http 2.0.0 to send files one by one. the go code is not expecting multiple files, only one.

Hi Santman,

I would first start learning about websockets, if you need to…

I like using Elixir for my backend with it’s Phoenix framework which comes with support for websockets built in.

How hard it would be for you would depend on your knowledge of websockets, and the backend you are using I guess.

There’s not really much code I can show you. I use my elm-phoenix-websocket package to talk to my Phoenix backend, so all I need to do is encode the data being sent with Json.Encode, send the data with Phoenix.push and create the handler on the relevant Phoenix channel to receive the data.

WRT to images I use the File module to grab the file data, then use File.toUrl to get the base64 string, and then encode it

Json.Encode.object
    [("file", Json.Encode.string base64String)]

And then push it to my channel.

In my case I don’t need progress reporting, and the data being sent is pretty small (50-60kb) after resizing and cropping with JS first. Progress reporting is possible, I just don’t need it.

HTH, sorry I can’t help more, hopefully it gives you some food for thought :slight_smile:

Hi @Warry thank you for your response.

Here in the document
https://package.elm-lang.org/packages/elm/http/latest/Http#multipartBody
It metiones that its a conventione followed in PHP and need not be the case for golang. I guess.

Adding the [] on repeated names is a convention from PHP. It seems weird, but I see it enough to mention it. You do not have to do it that way, especially if your server uses some other convention!

However even I did change the value to myFile[] on the Elm code and adjusted the same in the golang server code to pick the correct tag. I still have the same issue.

I’m using the multipartBody. to create a multipartBody I need to use filepart and not filebody

from the official document

multipartBody
  [ stringPart "title" "Trip to London"
  , filePart "album[]" file1
  , filePart "album[]" file2
  , filePart "album[]" file3
  ]

Since I’m sending the data as “form data” and on the server side as of now I only know how to receive the files using the

I have to use “multipartbody” on the Elm side.

Please let me know if I’m missing any point you are hinting me at.

I’ve disabled multiple file selection option

So the UI lets me pick only one file.

When this was enabled I did notice that server was picking the last selected file when working.
For example , if I select file a.txt first and then b.txt and when I click the submit button. Go was copying only “b.txt” and ignoring the “a.txt” file. Since it was not working for multiple file selections. I decided to go with one file selection to isolate the problem, Once I get this file upload for any type of file works for one file consistently, I will try to select multiple files and see how it behaves.

Thank you @paulh for the suggestions and links. I will go over them shortly and create a separate thread to discuss more on the web-sockets if required :slight_smile:

yeah, you had to go one way or the other: limiting to one file in the frontend, or switch to file body both in client and server sides.