如何下载文件并在clojure中从内存中解压缩?

pro*_*uga 7 clojure

我正在使用clj-http发出GET请求,响应是一个zip文件.此zip的内容始终是一个CSV文件.我想将CSV文件保存到磁盘,但我无法弄清楚如何.

如果我有磁盘上的文件,(fs/unzip filename destination)从Raynes/fs库工作得很好,但我无法弄清楚如何将clj-http的响应强制转换成可以读取的内容.如果可能的话,我想直接解压缩文件

我得到的最接近的(如果它甚至接近)让我进入BufferedInputStream,但我从那里迷路了.

(require '[clj-http.client :as client])
(require '[clojure.java.io :as io])

(->
  (client/get "http://localhost:8000/blah.zip" {:as :byte-array})
  (:body)
  (io/input-stream))
Run Code Online (Sandbox Code Playgroud)

Vik*_* K. 10

您可以使用纯java java.util.zip.ZipInputStreamjava.util.zip.GZIPInputStream.取决于内容的压缩方式.这是使用java.util.zip.GZIPInputStream保存文件的代码:

(->
  (client/get "http://localhost:8000/blah.zip" {:as :byte-array})
  (:body)
  (io/input-stream)
  (java.util.zip.GZIPInputStream.)
  (clojure.java.io/copy (clojure.java.io/file "/path/to/output/file")))
Run Code Online (Sandbox Code Playgroud)

使用java.util.zip.ZipInputStream使它变得有点复杂:

(let [stream (->
                (client/get "http://localhost:8000/blah.zip" {:as :byte-array})
                (:body)
                (io/input-stream)
                (java.util.zip.ZipInputStream.))]
      (.getNextEntry stream)
      (clojure.java.io/copy stream (clojure.java.io/file "/path/to/output/file")))
Run Code Online (Sandbox Code Playgroud)

  • 如果有人好奇,*after* 您在流上调用 .getNextEntry 之后,您可以针对流调用函数以获取第一个文件的内容。例如,如果文件是 CSV 或 JSON,您可以执行 (slurp stream) 来获取字符串,而不是上面示例中的最后一行(io/copy 流路径)。 (2认同)

小智 6

(require '[clj-http.client :as httpc])
(import '[java.io File])


(defn download-unzip [url dir]
  (let [saveDir (File. dir)]
    (with-open [stream (-> (httpc/get url {:as :stream})
                           (:body)
                           (java.util.zip.ZipInputStream.))]
      (loop [entry (.getNextEntry stream)]
        (if entry
          (let [savePath (str dir File/separatorChar (.getName entry))
                saveFile (File. savePath)]
            (if (.isDirectory entry)
              (if-not (.exists saveFile)
                (.mkdirs saveFile))
              (let [parentDir (File. (.substring savePath 0 (.lastIndexOf savePath (int File/separatorChar))))]
                (if-not (.exists parentDir) (.mkdirs parentDir))
                (clojure.java.io/copy stream saveFile)))
            (recur (.getNextEntry stream))))))))
Run Code Online (Sandbox Code Playgroud)