Search code examples
byteelmdecoding

Elm byte decoding within Http.get


I'm pretty new to elm and stuck with a problem regarding populating my model with data from my backend. I'm curently able to make a get request to the server which returns a byte[] (the data is any kind of image,audio or video), which works fine when just displaying this data by for example Html.img. When I try to use Http.get (src: https://package.elm-lang.org/packages/elm/http/latest/Http) to populate my model it requires a decoder. The problem is, that Bytes.Decode.bytes requires an Int to know how many bytes have to be decoded. So my question is: Is there any way to access the byte width while still matching the type pattern of Http.get?

Here's a simple example of my problem:


import Bytes exposing (Bytes)
import Bytes.Decode exposing (Decoder, bytes, decode)
import GeneralTypes exposing (Msg(..))
import Http

getMediaFromUrl : Cmd Msg
getMediaFromUrl = Http.get
        { url = "http://localhost:8090/image/2006/aa@a.de/session"
        , expect = Http.expectBytes GetThumbnail decodeBytes
        }

decodeBytes: Bytes.Bytes -> Decoder Bytes
decodeBytes bytesToDecode= let
                fileSize =
                    bytesToDecode |> Bytes.width
              in
              Bytes.Decode.bytes fileSize
module GeneralTypes exposing (..)

import Bytes exposing (Bytes)
import Http

type Msg = GetThumbnail (Result Http.Error Bytes)

Solution

  • The expectBytes function requires you to specify a Bytes decoder, which is useful if you immediately want to translate the bytes into something more meaningful in your code.

    If, however, you want to retain the raw Bytes in your application without having to clone or otherwise read the bytes at this time, you may find expectBytesResponse more useful. It has the signature:

    expectBytesResponse : (Result x a -> msg) -> (Response Bytes -> Result x a) -> Expect msg
    

    This does not take a decoder as input. It takes two functions which let you translate Response Bytes to a Result and another function (the first argument) which lets you translate that Result into a Msg. Through each of those steps you can retain the original Bytes reference, to do with as you please at a later time.

    You will, however, have to manually handle more HTTP response scenarios, but at least you gain full control over what to do with your Bytes.