2016-09-02 45 views
8

bir halka web uygulamasında bir zip dosyası akışı Ben gereken bir Yüzük işleyicisi vardır:oluşturun ve Clojure

  • Zip birkaç dosyalar
  • Akış müşteriye Zip.

Şimdi bir çeşit çalışmaya sahibim, ancak yalnızca ilk sıkıştırılmış giriş akışı gerçekleştiriliyor ve bundan sonra duruyor/duruyor. Sifresiz/akışlı bir şeylerin yanlış olduğunu hissediyorum. İşte

benim (compojure) işleyicisi olan: Burada

(GET "/zip" {:as request} 
      :query-params [order-id :- s/Any] 
      (stream-lessons-zip (read-string order-id) (:db request) (:auth-user request))) 

akışı-dersleri-zip fonksiyonudur:

(defn stream-lessons-zip 
    [] 
    (let [lessons ...];... not shown 

    {:status 200 
    :headers {"Content-Type" "application/zip, application/octet-stream" 
      "Content-Disposition" (str "attachment; filename=\"files.zip\"") 
    :body (futil/zip-lessons lessons)})) 

Ve böyle akışı yapmak için bir borulu-girdi-akışı kullanmak böylece:

(defn zip-lessons 
"Returns an inputstream (piped-input-stream) to be used directly in Ring HTTP responses" 
[lessons] 
(let [paths (map #(select-keys % [:file_path :file_name]) lessons)] 
(ring-io/piped-input-stream 
    (fn [output-stream] 
    ; build a zip-output-stream from a normal output-stream 
    (with-open [zip-output-stream (ZipOutputStream. output-stream)] 
     (doseq [{:keys [file_path file_name] :as p} paths] 
     (let [f (cio/file file_path)] 
      (.putNextEntry zip-output-stream (ZipEntry. file_name)) 
      (cio/copy f zip-output-stream) 
      (.closeEntry zip-output-stream)))))))) 

Yani 'dersleri' vektör 4 girişleri gibi içerdiğini doğruladı, ancak zip dosyası sadece 1 e içeriyor ntry. Ayrıca, Chrome, indirme işlemini 'sonlandırmak' gibi görünmüyor. hala indiriliyor sanıyor.

Bunu nasıl düzeltebilirim?

+0

closeEntry çağrısından önce doseq içine (.flush zip-output-stream) eklemeyi denedim, ancak boşuna. –

+1

Kodunuzun basitleştirilmiş sürümünü denedim ve iyi çalışıyor. Bence sorunlara sebep olan orta sınıflardan biri olabilir. Uygulamanızı hiçbir ya da minimal orta sınıf seti ile çalıştırmayı deneyip çalıştıramayacağınızı görebilirsiniz. –

+1

http-kit kullanıyor olmuyor musunuz? İndirme işlemlerini buna göre yapmaya çalışmakla ilgili sorunlar yaşadım, desteklendiğine inanmıyorum, oysa ring-jetty. – Russell

cevap

1

Bloke edici bir IO kullanarak durumlu bir akış oluşturmak gibi görünüyor, http-kit tarafından desteklenmiyor.

http://www.http-kit.org/server.html#async

A PR IO engelleme kullanarak durum bilgisi akışları tanıtmak kabul edilmedi:

https://github.com/http-kit/http-kit/pull/181

iyice incelemek seçeneği etmektir sesler gibi olmayan durum bilgisi akışları bu şekilde yapılabilir zip dosyasını belleğe tam olarak oluşturmak için bir ByteArrayOutputStream kullanın ve sonra da üreten arabelleği döndürün. Bu son nokta çok fazla trafiğe eklenmemişse ve ürettiği zip dosyası büyük değilse (< 1 gb), bu işe yarayabilir.