         con (.openConnection url)]
     (.getContentLength con)))
 
+(defn- percentage-slices
+  "Returns a seq of maps of length num-slices where each map represents the
+  percentage and the associated percentage of size
+
+  usage:
+  (percentage-slices 1000 2) ;=> ({:perc 50N, :val 500N} {:perc 100, :val 1000})"
+  [size num-slices]
+  (map (fn [slice]
+         (let [perc (/ (inc slice) num-slices)]
+           {:perc (* 100 perc)
+            :val  (* size perc)}))
+       (range num-slices)))
+
+(defn- print-file-copy-status
+  "Print copy status in percentage - granularity times - evenly as
+  num-copied-bytes approaches file-size"
+  [num-copied-bytes buf-size file-size slices]
+  (let [min    num-copied-bytes
+        max    (+ buf-size num-copied-bytes)]
+    (when-let [slice (some (fn [slice]
+                             (when (and (> (:val slice) min)
+                                        (< (:val slice) max))
+                               slice))
+                           slices)]
+      (println (str (:perc slice) "% completed")))))
+
+(defn remote-file-copy [in-stream out-stream file-size]
+  (let [buf-size 2048
+        buffer   (make-array Byte/TYPE buf-size)
+        slices   (percentage-slices file-size 100)]
+    (loop [bytes-copied 0]
+      (let [size (.read in-stream buffer)]
+        (when *verbose-overtone-file-helpers*
+          (print-file-copy-status bytes-copied size file-size slices))
+        (when (pos? size)
+          (do (.write out-stream buffer 0 size)
+              (recur (+ size bytes-copied))))))))
+
 (defn- download-file-without-timeout
   "Downloads remote file at url to local file specified by target path. Has
   potential to block current thread whilst reading data from remote host. See

     (let [path (resolve-tilde-path path)]
       (try
         (download-file-with-timeout url path timeout)
         (catch java.io.IOException e
           (rm-rf! path)
           (Thread/sleep wait-t)
           (download-file* url path timeout n-retries wait-t (inc attempts-made)))))))

(defn- print-download-file

  java.net.SocketTimeoutException"
  [url target-path timeout]
  (let [target-path (resolve-tilde-path target-path)
        size        (remote-file-size url)
        url         (URL. url)
        con         (.openConnection url)]
    (.setReadTimeout con timeout)
    (with-open [in (.getInputStream con)
                out (output-stream target-path)]
      (remote-file-copy in out size))
    target-path))

(defn get-file-with-timeout
  "Returns a stringified version of the file pointed to by url. If download
  stalls for more than timeout ms an exception is thrown."
  [url timeout]
  (let [url  (URL. url)
        con  (.openConnection url)
        size (remote-file-size url)]
    (.setReadTimeout con timeout)
    (with-open [in (.getInputStream con)
                out (StringWriter.)]
      (copy in out size)
      (.toString out))))

(defn file-size
