elm / http

Make HTTP requests in Elm
https://package.elm-lang.org/packages/elm/http/latest
BSD 3-Clause "New" or "Revised" License
154 stars 46 forks source link

No method for creating fileParts from non-File types #63

Open paul-freeman opened 5 years ago

paul-freeman commented 5 years ago

The https://github.com/elm/file package provides methods for downloading strings and bytes as files, but similar methods are not included with this package. This makes it difficult for an application to generate files that can be posted with Http.multipartBody.

Expected behavior would be to shortcut these (UX-poor) steps:

  1. File.Download.bytes (have user download file)
  2. File.Select.file (have user select the same file)
  3. Http.filePart (create a file part)
  4. Http.post (post to server)

The net result of the above steps is essentially nothing more than attaching a name to a Blob, resulting in a File. Similar steps would be used for string data.

One possible solution might be to add a function: bytesPartToFilePart : String -> Part -> Part to explicitly name a bytes blob.

A second solution might be to add functions to go directly from strings and bytes to file bodies.

I am proposing this change as I feel it is a relatively simple change that will open up a large variety of HTTP-based storage options for future Elm applications. I am personally exploring decentralized application file storage via IPFS and have hit a few walls from not having this feature.

paul-freeman commented 5 years ago

I will also add that this issue can be summarized as an attempt to complete the example listed in the documentation for Http.Body.bytesBody.

For example, you could create an archive.zip file and send it along like this

Afterwards, sample code is provided, but makes no mention as to how those bytes come to be named archive.zip (presumably through server-side code).

evancz commented 5 years ago

I'm having trouble understanding the thing you want to do, so I am going to try to say what I understand.

There are a couple ways to create Part values right now:

I believe the difference in the HTTP request produced is whether a file name is associated with the part in the body. You want to send a file you made in browser though, so it is annoying that there is not an easy way to create a part with custom bytes and a custom file name.

Is that correct?

If so, I think the path would be to add functions to the File module for creating files locally. Something like File.fromBytes : String -> String -> Bytes -> File and an equivalent one for fromString. I'll need to get back into the whole File API in JS to see exactly what information is needed to make this reliable, but that's the direction that jumps out to me.

Note: I'm not sure when HTTP and files will get another batch of work, so I recommend using ports in the meantime.

paul-freeman commented 5 years ago

You want to send a file you made in browser though, so it is annoying that there is not an easy way to create a part with custom bytes and a custom file name.

Absolutely correct.

Something like File.fromBytes : String -> String -> Bytes -> File and an equivalent one for fromString.

Yes. I think this would be ideal and simple to understand.

This SO post seems to indicate that a Blob and a File are nearly identical, suggesting this (slightly edited by me) JS transformation:

function blobToFile(theBlob, fileName){
    theBlob.lastModified = new Date();
    theBlob.name = fileName;
    return theBlob;
}

Basically, you just add the filename and date. Technically, the definition of File lists 4 fields not inherited from Blob, but 1 is deprecated and 1 is non-standardized. I think the change would be straightforward.

More than happy to use ports in the meantime. And would be happy to submit a PR if requested. :)

As background, I'm working for a decentralized messaging app startup Sylo. The browser version of our app is being written in Elm (we've got about 10K LOC) and will be released soon. My need for a resolution to this issue stems from my desire to give back to the Elm community. We use many Web RPC services, and if I can turn some of them into Elm packages, I would enjoy being able to do that for everyone. Specifically blocked are a number of improvements to the paul-freeman/elm-ipfs package.