Using piped-input-stream from ring.utils.io to serve files
Asked Answered
G

1

6

I need to create on the fly excel file on request and serve it to user via response, using clojure.ring.

I use docjure to create an excel file and write it to the output stream (see this function: https://github.com/mjul/docjure/blob/master/src/dk/ative/docjure/spreadsheet.clj#L86), and I get the output stream from using piped-input-stream (see https://github.com/ring-clojure/ring/blob/1.5.0/ring-core/src/ring/util/io.clj#L11).

The relevant part of code:

(defn excel-response
  [params]
  (-> (response (piped-input-stream (fn [out-stream]
                                  (create-excel-into-stream out-stream
                                                            params))))
      (assoc :headers {"Content-Type"
                       "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"})))

Using this function, I always get an empty .xlsx file for some reasons. It seems like piped-input-stream closes before I can serve it as the body of my response.

How do I use it properly, so I can write to output stream, pass it to input stream and then serve as the body of response?

Germano answered 13/10, 2016 at 13:12 Comment(2)
Three ideas to look at: Does create-excel-into-stream create content? Are the streams connected with each other? Are both streams on different threads?Laubin
1. It does create content. 2. They are connected via .connect inside piped-input-stream function, see the link to code in my question. 3. No threads are created, the piped-input-stream function uses future to process output stream. I actually didn't add much to current code, just used piped-input-stream as is. Am I missing something?Germano
C
0

Your excel-response function looks correct to me, I've written something very similar before. What does your create-excel-into-stream function look like?

This has worked for me in the past.

(ns my.data.handler
  (:require [clojure.data.csv :as csv]
            [clojure.java.io :as io]))

(defn create-excel-into-stream
  [out-stream params]
  (let [excel-data (get-excel-data params)]
    (with-open [writer (io/writer out-stream)]
      (csv/write-csv writer excel-data))))
Claytor answered 20/1, 2017 at 15:27 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.