Last active
July 9, 2020 13:32
-
-
Save henryw374/1392de5fedcf540648b015c65c7fc4d3 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(ns ftp-client | |
(:require | |
[clojure.java.io :as io] | |
[clojure.tools.logging :as log] | |
[miner.ftp :as ftp]) | |
(:import [java.nio.file Path Paths Files FileSystem FileSystems] | |
[java.nio.file.attribute FileAttribute] | |
[java.io File])) | |
(defn remove! | |
"Removes the contents under the given location. | |
Returns nil if an error was encountered during the operation, true otherwise." | |
[url location] | |
(try | |
(let [success? (ftp/with-ftp [client url] | |
(ftp/client-delete client location))] | |
(if success? true | |
(log/error "Could not remove:" url "/" location "!"))) | |
(catch Exception e | |
(log/error e "Could not remove:" url "/" location "!")))) | |
(defn list-objects | |
"Accepts the glob arg filter out resources based on | |
the file name" | |
([url] (list-objects url "*")) | |
([url glob] | |
(ftp/with-ftp [client url] | |
(seq (mapv #(.getName %) | |
(.listFiles client glob)))))) | |
(defn apply-stream-to | |
"Opens a stream to the content stored in ftp server and calls f with it. | |
throws if file not found, otherwise, returns the result of applying f" | |
[url location f] | |
(ftp/with-ftp [client url :file-type :binary] | |
(if-let [stream (ftp/client-get-stream client location)] | |
(with-open [input stream] | |
(let [result (f input)] | |
(ftp/client-complete-pending-command client) | |
result)) | |
(throw | |
(java.io.FileNotFoundException. | |
(format "could not find %s at %s " location url)))))) | |
(defn- dir-path-from-location [location] | |
(-> location | |
clojure.java.io/as-file | |
(.getParent))) | |
(defn- make-directory-structure [url dir-path] | |
(ftp/with-ftp [client url] | |
(let [dirs (.split dir-path "/")] | |
(loop [next-dir (first dirs) | |
remaining (rest dirs)] | |
(when-not (.changeWorkingDirectory client next-dir) | |
(if (.makeDirectory client next-dir) | |
(.changeWorkingDirectory client next-dir) | |
(throw (Exception. (str "couldnt make dir " next-dir))))) | |
(when (not-empty remaining) | |
(recur | |
(first remaining) | |
(rest remaining))))))) | |
(defn store-if-not-exists! | |
"Stores given input under the given location. Returns nil in case of failure. | |
input can either be a string that will work with clojure.java.io/as-file, or a java.io.InputStream | |
" | |
[url location input] | |
(try | |
(if (list-objects url location) | |
(log/info "Content under" url "/" location "already exists!") | |
(do (log/debug "Storing" input "in" url "/" location "...") | |
(ftp/with-ftp [client url | |
:file-type :binary] | |
(when-let [dir-path (dir-path-from-location location)] | |
(make-directory-structure url dir-path)) | |
(let [input-stream (if (instance? java.io.InputStream input) | |
input | |
(java.io.FileInputStream. (io/as-file input))) | |
success? (with-open [instream input-stream] | |
(.storeFile client location instream))] | |
(if success? true | |
(log/error "Could not upload:" input " to " url "/" location "!")))))) | |
(catch Exception e | |
(log/error e "Could not upload:" input " to " url "/" location "!") | |
(remove! url location)))) | |
(defn- escape [s] | |
(when s (java.net.URLEncoder/encode s "UTF-8"))) | |
(defn- format-url [host port username password] | |
(let [username (escape username) | |
password (escape password) | |
host-port (if port (str host ":" port) host) | |
user-pass (if password (str username ":" password) username)] | |
(format "ftp://%s@%s" user-pass host-port))) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment