2016-09-02 20 views
8

Tôi có một handler nhẫn mà cần phải:Tạo và dòng một zip-file trong một ứng dụng web Ring trong Clojure

  • Zip một vài tác phẩm
  • Luồng Zip cho khách hàng.

Bây giờ tôi có loại hoạt động, nhưng chỉ mục nhập nén đầu tiên mới được truyền trực tuyến và sau đó nó dừng/dừng lại. Tôi cảm thấy nó có một cái gì đó để làm với xả/streaming đó là sai.

Sau đây là tôi (compojure) handler:

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

Dưới đây là chức năng stream-học-zip:

(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)})) 

Và tôi sử dụng một đường ống-input-stream để làm trực tuyến như như vậy:

(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)))))))) 

Vì vậy, tôi đã xác nhận rằng 'bài học' vectơ chứa 4 mục, nhưng tệp zip chỉ chứa 1 e ntry. Hơn nữa, Chrome dường như không 'hoàn thành' bản tải xuống, nghĩa là. nó nghĩ rằng nó vẫn đang tải xuống.

Làm cách nào để khắc phục sự cố này?

+0

Tôi đã thử thêm (.flush zip-output-stream) vào liều lượng trước cuộc gọi closeEntry, nhưng không có kết quả. –

+1

Tôi đã thử phiên bản mã đơn giản của bạn và nó hoạt động tốt. Tôi nghĩ rằng nó có thể là một số phần giữa gây ra vấn đề. Bạn có thể thử chạy ứng dụng của mình mà không có hoặc thiết lập các phần mềm trung gian tối thiểu và xem nó có hoạt động hay không. –

+1

Bạn không có ý định sử dụng bộ http làm bạn? Tôi đã gặp sự cố với việc cố gắng tải xuống các bản tải xuống với điều đó, tôi không tin rằng nó được hỗ trợ, trong khi đó là do cầu cảng. – Russell

Trả lời

1

Có vẻ như việc tạo luồng trạng thái bằng cách chặn chặn IO không được bộ http hỗ trợ. suối phi stateful thể được thực hiện theo cách này:

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

Một PR để giới thiệu dòng stateful sử dụng chặn IO không được chấp nhận:

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

Nghe có vẻ như tùy chọn để khám phá là sử dụng một ByteArrayOutputStream để hoàn toàn làm cho tệp zip vào bộ nhớ, và sau đó trả về bộ đệm tạo ra. Nếu điểm cuối này không được quản lý cao và tệp nén mà nó tạo ra không lớn (< 1 gb) thì điều này có thể hoạt động.

Các vấn đề liên quan