Base64 encoding/decoding


#1

I just published my first package! It’s for encoding and decoding Base64 strings to and from Bytes.

Initially I wanted to use it with jxxcarlson/elm-tar to compress and encode text from a page in its url, but I was too optimistic about tar’s compression and the resulting Base64 string was far too long.

If anyone has a cool use case for it I’d love to add it to the package’s examples, because right now I only have a text encoding demo (which is still kind of cool.)


#2

Thanks, I was waiting for this! My use case is to load a png image via http and to display it with an <img> tag as a base64 encoded url.

Unfortunately, it doesn’t work – fromBytes returns Nothing.

I reproduced it with a random image from the web (http://pngimagesfree.com/NATURE/Tree/tree_png_24.png). Just put the image near Main.elm and run it with elm-reactor (and you should see Nothing in the console):

module Main exposing (main)

import Base64
import Browser
import Bytes exposing (Bytes)
import Http


type alias Model =
    ()


type Msg
    = GotImage (Result Http.Error Bytes)


main : Program () Model Msg
main =
    Browser.document
        { init = \() -> init
        , subscriptions = \_ -> Sub.none
        , view = \_ -> { title = "", body = [] }
        , update = update
        }


init : ( Model, Cmd Msg )
init =
    ( ()
    , Http.get
        { url = "/tree_png_24.png"
        , expect =
            Http.expectBytesResponse GotImage <|
                \response ->
                    case response of
                        Http.BadUrl_ url ->
                            Err (Http.BadUrl url)

                        Http.Timeout_ ->
                            Err Http.Timeout

                        Http.NetworkError_ ->
                            Err Http.NetworkError

                        Http.BadStatus_ metadata body ->
                            Err (Http.BadStatus metadata.statusCode)

                        Http.GoodStatus_ metadata body ->
                            Ok body
        }
    )


update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
    case msg of
        GotImage (Ok bytes) ->
            let
                _ =
                    Debug.log "base64" (Base64.fromBytes bytes)
            in
            ( ()
            , Cmd.none
            )

        GotImage (Err err) ->
            let
                _ =
                    Debug.log "err" err
            in
            ( ()
            , Cmd.none
            )

#3

Thanks for catching that! It should work in 1.0.1.
I had a recursive function that wasn’t tail call optimized and that caused a stack overflow.
I also found a bug in elm/bytes and a bug in elm-test along the way :sweat_smile:


#4

thank you, it works!


#5

I think this is because tar just groups files together. Folk use schemes like gzip or bzip to actually do the compression (but they can only work on single files, hence tar).

See: https://unix.stackexchange.com/questions/127169/does-tar-actually-compress-files-or-just-group-them-together


#6

Also tar is awful for tiny files (without additional compression) because minimum size of tar-file is 10240 bytes, even if you only include one single-byte file. (But most of that is just zeros, so it will compress well when using some additional compression).