gpt4 book ai didi

csv - 如何从 compojure API 流式传输大型 CSV 响应,以便整个响应不会立即保存在内存中?

转载 作者:行者123 更新时间:2023-12-04 20:43:04 27 4
gpt4 key购买 nike

我是使用 compojure 的新手,但到目前为止一直很喜欢使用它。我是
当前在我的 API 端点之一中遇到问题,该问题正在生成
从数据库中提取一个大型 CSV 文件,然后将其作为响应正文传递。

我似乎遇到的问题是整个 CSV 文件都被保留了
在内存中,然后导致 API 中的内存不足错误。是什么
处理和生成它的最佳方法,最好是作为 gzip 文件?是否可以
流式传输响应以便一次返回几千行?什么时候
我为相同的数据返回了一个JSON响应体,返回没有问题
这个。

这是我用来返回的当前代码:

(defn complete
"Returns metrics for each completed benchmark instance"
[db-client response-format]
(let [benchmarks (completed-benchmark-metrics {} db-client)]
(case response-format
:json (json-grouped-output field-mappings benchmarks)
:csv (csv-output benchmarks))))

(defn csv-output [data-seq]
(let [header (map name (keys (first data-seq)))
out (java.io.StringWriter.)
write #(csv/write-csv out (list %))]
(write header)
(dorun (map (comp write vals) data-seq))
(.toString out)))
data-seq是从数据库返回的结果,我认为是
懒惰的序列。我正在使用 yesql 来执行数据库调用。

这是我针对此 API 端点的 Compojure 资源:
(defresource results-complete [db]
:available-media-types ["application/json" "text/csv"]
:allowed-methods [:get]
:handle-ok (fn [request]
(let [response-format (keyword (get-in request [:request :params :format] :json))
disposition (str "attachment; filename=\"nucleotides_benchmark_metrics." (name response-format) "\"")
response {:headers {"Content-Type" (content-types response-format)
"Content-Disposition" disposition}
:body (results/complete db response-format)}]
(ring-response response))))

最佳答案

感谢这个线程中提供的所有建议,我能够使用 piped-input-stream 创建一个解决方案:

(defn csv-output [data-seq]
(let [headers (map name (keys (first data-seq)))
rows (map vals data-seq)
stream-csv (fn [out] (csv/write-csv out (cons headers rows))
(.flush out))]
(piped-input-stream #(stream-csv (io/make-writer % {})))))

这与我的解决方案不同,因为它没有使用 dorun 实现序列并且不会产生大 String对象。这反而写入 PipedInputStream异步连接 as described by the documentation :

Create an input stream from a function that takes an output stream as its argument. The function will be executed in a separate thread. The stream will be automatically closed after the function finishes.

关于csv - 如何从 compojure API 流式传输大型 CSV 响应,以便整个响应不会立即保存在内存中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46288109/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com