2

I'm attempting to use the following code to base64 encode an image and then email it using a third-party email service.

(ns application.encode
  (:import org.apache.commons.codec.binary.Base64)
  (:require [clojure.java.io :as io]))

(defn encode [file-path]
  (let [content (String. 
                  (Base64/encodeBase64 
                    (.getBytes 
                      (slurp (clojure.java.io/resource "public/test.gif")))))]

    ;; email file contents
)

However, the image is being corrupted and its size is being doubled. I'm able to verify this either by sending it via email or spitting it to a local file.

What am I doing incorrectly?

UPDATE: In case it's useful, the following Ruby code does what I'm trying to do above and writing its output to a file, then slurping it allows me to send the email as desired. (This isn't a solution, of course, but I wanted to make sure what I'm trying to do was even possible using the file in question.)

encoded = Base64.encode64(File.read('resources/public/test.gif'))

pdoherty926
  • 9,895
  • 4
  • 37
  • 68

2 Answers2

4

First of all, significant increase in size is expected for base64 but not exactly doubling of course.

I'm not a Clojure developer but I beliveve that the issue is aroud slurp + getBytes. Unfortunately you can't just read file as string and use .getBytes and expect to get original file contents because of various issues introduced by encoding. You should read file directly as bytes array. This SO answer suggest there is no such standard function but slurp-bytes from the second answer looks quite promising to me.

Community
  • 1
  • 1
SergGr
  • 23,570
  • 2
  • 30
  • 51
  • My misuse of `slurp` was indeed the cause of my problem. Using information provided by the answer you linked to, I was able to find a working solution. Thanks! – pdoherty926 Mar 01 '17 at 14:17
2

Please see this closely related question and answer from this week: Slurping http://foobar.mp3 that redirects to http://fizzbar.mp3 in Clojure

Basically, slurp is for text files only.

For full information, please bookmark and keep open in a browser tab the Clojure Cheatsheet. Also, see the specific docs for the slurp function.

A nice example can be found in the Clojure Cookbook: https://github.com/clojure-cookbook/clojure-cookbook/blob/master/04_local-io/4-19_handle-binary-files.asciidoc

More examples can be found on ClojureDocs: https://clojuredocs.org/clojure.java.io/input-stream

Community
  • 1
  • 1
Alan Thompson
  • 29,276
  • 6
  • 41
  • 48