0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-02-13 18:48:37 -05:00

Merge pull request #2381 from penpot/niwinz-chunked-exports

 Make the exportation streaming directly to response
This commit is contained in:
Alejandro 2022-10-04 10:55:49 +02:00 committed by GitHub
commit 3044d0abcc
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 39 additions and 22 deletions

View file

@ -280,7 +280,7 @@
(assoc ::binf/file-ids file-ids) (assoc ::binf/file-ids file-ids)
(assoc ::binf/embed-assets? embed?) (assoc ::binf/embed-assets? embed?)
(assoc ::binf/include-libraries? libs?) (assoc ::binf/include-libraries? libs?)
(binf/export!))] (binf/export-to-tmpfile!))]
(if clone? (if clone?
(let [project-id (some-> (profile/retrieve-additional-data pool profile-id) :default-project-id)] (let [project-id (some-> (profile/retrieve-additional-data pool profile-id) :default-project-id)]
(binf/import! (binf/import!

View file

@ -30,7 +30,8 @@
[clojure.walk :as walk] [clojure.walk :as walk]
[cuerdas.core :as str] [cuerdas.core :as str]
[datoteka.io :as io] [datoteka.io :as io]
[yetti.adapter :as yt]) [yetti.adapter :as yt]
[yetti.response :as yrs])
(:import (:import
com.github.luben.zstd.ZstdInputStream com.github.luben.zstd.ZstdInputStream
com.github.luben.zstd.ZstdOutputStream com.github.luben.zstd.ZstdOutputStream
@ -799,27 +800,40 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defn export! (defn export!
[cfg] [cfg output]
(let [path (tmp/tempfile :prefix "penpot.export.") (let [id (uuid/next)
id (uuid/next) tp (dt/tpoint)
ts (dt/now) ab (volatile! false)
cs (volatile! nil)] cs (volatile! nil)]
(try (try
(l/info :hint "start exportation" :export-id id) (l/info :hint "start exportation" :export-id id)
(with-open [output (io/output-stream path)] (with-open [output (io/output-stream output)]
(binding [*position* (atom 0)] (binding [*position* (atom 0)]
(write-export! (assoc cfg ::output output)) (write-export! (assoc cfg ::output output))))
path))
(catch java.io.IOException _cause
;; Do nothing, EOF means client closes connection abruptly
(vreset! ab true)
nil)
(catch Throwable cause (catch Throwable cause
(vreset! cs cause) (vreset! cs cause)
(vreset! ab true)
(throw cause)) (throw cause))
(finally (finally
(l/info :hint "exportation finished" :export-id id (l/info :hint "exportation finished" :export-id id
:elapsed (str (inst-ms (dt/diff ts (dt/now))) "ms") :elapsed (str (inst-ms (tp)) "ms")
:aborted @ab
:cause @cs))))) :cause @cs)))))
(defn export-to-tmpfile!
[cfg]
(let [path (tmp/tempfile :prefix "penpot.export.")]
(with-open [output (io/output-stream path)]
(export! cfg output)
path)))
(defn import! (defn import!
[{:keys [::input] :as cfg}] [{:keys [::input] :as cfg}]
(let [id (uuid/next) (let [id (uuid/next)
@ -855,17 +869,20 @@
"Export a penpot file in a binary format." "Export a penpot file in a binary format."
{::doc/added "1.15"} {::doc/added "1.15"}
[{:keys [pool] :as cfg} {:keys [profile-id file-id include-libraries? embed-assets?] :as params}] [{:keys [pool] :as cfg} {:keys [profile-id file-id include-libraries? embed-assets?] :as params}]
(db/with-atomic [conn pool] (files/check-read-permissions! pool profile-id file-id)
(files/check-read-permissions! conn profile-id file-id) (let [resp (reify yrs/StreamableResponseBody
(let [path (export! (assoc cfg (-write-body-to-stream [_ _ output-stream]
::file-ids [file-id] (-> cfg
::embed-assets? embed-assets? (assoc ::file-ids [file-id])
::include-libraries? include-libraries?))] (assoc ::embed-assets? embed-assets?)
(with-meta {} (assoc ::include-libraries? include-libraries?)
{:transform-response (fn [_ response] (export! output-stream))))]
(assoc response
:body (io/input-stream path) (with-meta (sv/wrap nil)
:headers {"content-type" "application/octet-stream"}))})))) {:transform-response (fn [_ response]
(-> response
(assoc :body resp)
(assoc :headers {"content-type" "application/octet-stream"})))})))
(s/def ::file ::media/upload) (s/def ::file ::media/upload)
(s/def ::import-binfile (s/def ::import-binfile