mirror of
https://github.com/penpot/penpot.git
synced 2025-02-02 20:39:09 -05:00
feat(backend): improve image uploading and thumbnail handling
This commit is contained in:
parent
820edba113
commit
e786a85bbd
6 changed files with 64 additions and 23 deletions
|
@ -5,7 +5,7 @@
|
||||||
funcool/cuerdas {:mvn/version "2.2.0"}
|
funcool/cuerdas {:mvn/version "2.2.0"}
|
||||||
|
|
||||||
funcool/datoteka {:git/url "https://github.com/funcool/datoteka.git"
|
funcool/datoteka {:git/url "https://github.com/funcool/datoteka.git"
|
||||||
:sha "b75f08fd59013577dd5e743d0b013dede6c6dc66"}
|
:sha "bae298a642b40e84e92dc195a68444bc63e807d9"}
|
||||||
|
|
||||||
funcool/struct {:mvn/version "1.4.0"}
|
funcool/struct {:mvn/version "1.4.0"}
|
||||||
|
|
||||||
|
|
|
@ -63,4 +63,5 @@ returning *;
|
||||||
-- :name delete-image :! :n
|
-- :name delete-image :! :n
|
||||||
update images
|
update images
|
||||||
set deleted_at = clock_timestamp()
|
set deleted_at = clock_timestamp()
|
||||||
where id = :id and "user" = :user;
|
where id = :id and "user" = :user
|
||||||
|
returning *;
|
||||||
|
|
|
@ -27,7 +27,8 @@
|
||||||
|
|
||||||
(defn- start
|
(defn- start
|
||||||
[]
|
[]
|
||||||
(mount/start))
|
(-> (mount/except #{#'uxbox.scheduled-jobs/scheduler})
|
||||||
|
(mount/start)))
|
||||||
|
|
||||||
(defn- stop
|
(defn- stop
|
||||||
[]
|
[]
|
||||||
|
|
|
@ -6,18 +6,20 @@
|
||||||
|
|
||||||
(ns uxbox.images
|
(ns uxbox.images
|
||||||
"Image postprocessing."
|
"Image postprocessing."
|
||||||
(:require [clojure.spec.alpha :as s]
|
(:require
|
||||||
[clojure.java.io :as io]
|
[clojure.java.io :as io]
|
||||||
[datoteka.storages :as st]
|
[clojure.spec.alpha :as s]
|
||||||
[datoteka.core :as fs]
|
[datoteka.core :as fs]
|
||||||
[datoteka.proto :as pt]
|
[datoteka.proto :as pt]
|
||||||
[uxbox.util.spec :as us]
|
[datoteka.storages :as st]
|
||||||
[uxbox.media :as media]
|
[uxbox.media :as media]
|
||||||
[uxbox.util.data :refer (dissoc-in)])
|
[uxbox.util.data :refer (dissoc-in)]
|
||||||
(:import java.io.InputStream
|
[uxbox.util.spec :as us])
|
||||||
|
(:import
|
||||||
java.io.ByteArrayInputStream
|
java.io.ByteArrayInputStream
|
||||||
org.im4java.core.IMOperation
|
java.io.InputStream
|
||||||
org.im4java.core.ConvertCmd))
|
org.im4java.core.ConvertCmd
|
||||||
|
org.im4java.core.IMOperation))
|
||||||
|
|
||||||
;; --- Thumbnails Generation
|
;; --- Thumbnails Generation
|
||||||
|
|
||||||
|
@ -59,13 +61,11 @@
|
||||||
{:pre [(us/valid? ::thumbnail-opts opts)
|
{:pre [(us/valid? ::thumbnail-opts opts)
|
||||||
(or (string? input)
|
(or (string? input)
|
||||||
(fs/path input))]}
|
(fs/path input))]}
|
||||||
(let [parent (fs/parent input)
|
(let [[filename ext] (fs/split-ext (fs/name input))
|
||||||
[filename ext] (fs/split-ext (fs/name input))
|
|
||||||
|
|
||||||
suffix (->> [width height quality format]
|
suffix (->> [width height quality format]
|
||||||
(interpose ".")
|
(interpose ".")
|
||||||
(apply str))
|
(apply str))
|
||||||
thumbnail-path (fs/path parent (str filename "-" suffix))
|
thumbnail-path (fs/path input (str "thumb-" suffix))
|
||||||
images-storage media/images-storage
|
images-storage media/images-storage
|
||||||
thumbs-storage media/thumbnails-storage]
|
thumbs-storage media/thumbnails-storage]
|
||||||
(if @(st/exists? thumbs-storage thumbnail-path)
|
(if @(st/exists? thumbs-storage thumbnail-path)
|
||||||
|
|
|
@ -9,11 +9,40 @@
|
||||||
(:require [mount.core :refer [defstate]]
|
(:require [mount.core :refer [defstate]]
|
||||||
[clojure.java.io :as io]
|
[clojure.java.io :as io]
|
||||||
[cuerdas.core :as str]
|
[cuerdas.core :as str]
|
||||||
|
[datoteka.core :as fs]
|
||||||
|
[datoteka.proto :as stp]
|
||||||
[datoteka.storages :as st]
|
[datoteka.storages :as st]
|
||||||
[datoteka.storages.local :refer [localfs]]
|
[datoteka.storages.local :refer [localfs]]
|
||||||
[datoteka.storages.misc :refer [hashed scoped]]
|
[datoteka.storages.misc :refer [hashed scoped]]
|
||||||
[uxbox.config :refer [config]]))
|
[uxbox.config :refer [config]]))
|
||||||
|
|
||||||
|
;; --- Backends
|
||||||
|
|
||||||
|
(defn- normalize-filename
|
||||||
|
[path]
|
||||||
|
(let [parent (or (fs/parent path) "")
|
||||||
|
[name ext] (fs/split-ext (fs/name path))]
|
||||||
|
(fs/path parent (str (str/uslug name) ext))))
|
||||||
|
|
||||||
|
(defrecord FilenameSlugifiedBackend [storage]
|
||||||
|
stp/IPublicStorage
|
||||||
|
(-public-uri [_ path]
|
||||||
|
(stp/-public-uri storage path))
|
||||||
|
|
||||||
|
stp/IStorage
|
||||||
|
(-save [_ path content]
|
||||||
|
(let [^Path path (normalize-filename path)]
|
||||||
|
(stp/-save storage path content)))
|
||||||
|
|
||||||
|
(-delete [_ path]
|
||||||
|
(stp/-delete storage path))
|
||||||
|
|
||||||
|
(-exists? [this path]
|
||||||
|
(stp/-exists? storage path))
|
||||||
|
|
||||||
|
(-lookup [_ path]
|
||||||
|
(stp/-lookup storage path)))
|
||||||
|
|
||||||
;; --- State
|
;; --- State
|
||||||
|
|
||||||
(defstate assets-storage
|
(defstate assets-storage
|
||||||
|
@ -29,10 +58,12 @@
|
||||||
(defstate images-storage
|
(defstate images-storage
|
||||||
:start (-> media-storage
|
:start (-> media-storage
|
||||||
(scoped "images")
|
(scoped "images")
|
||||||
(hashed)))
|
(hashed)
|
||||||
|
(->FilenameSlugifiedBackend)))
|
||||||
|
|
||||||
(defstate thumbnails-storage
|
(defstate thumbnails-storage
|
||||||
:start (scoped media-storage "thumbs"))
|
:start (-> media-storage
|
||||||
|
(scoped "thumbs")))
|
||||||
|
|
||||||
;; --- Public Api
|
;; --- Public Api
|
||||||
|
|
||||||
|
|
|
@ -199,10 +199,18 @@
|
||||||
|
|
||||||
;; --- Delete Image
|
;; --- Delete Image
|
||||||
|
|
||||||
|
(defn- delete-image-from-storage
|
||||||
|
[{:keys [path] :as image}]
|
||||||
|
(when @(st/exists? media/images-storage path)
|
||||||
|
@(st/delete media/images-storage path))
|
||||||
|
(when @(st/exists? media/thumbnails-storage path)
|
||||||
|
@(st/delete media/thumbnails-storage path)))
|
||||||
|
|
||||||
(defn delete-image
|
(defn delete-image
|
||||||
[conn {:keys [user id]}]
|
[conn {:keys [user id]}]
|
||||||
(let [sqlv (sql/delete-image {:id id :user user})]
|
(let [sqlv (sql/delete-image {:id id :user user})]
|
||||||
(pos? (sc/execute conn sqlv))))
|
(some-> (sc/fetch-one conn sqlv)
|
||||||
|
(delete-image-from-storage))))
|
||||||
|
|
||||||
(s/def ::delete-image
|
(s/def ::delete-image
|
||||||
(s/keys :req-un [::user]
|
(s/keys :req-un [::user]
|
||||||
|
@ -212,7 +220,7 @@
|
||||||
[params]
|
[params]
|
||||||
(s/assert ::delete-image params)
|
(s/assert ::delete-image params)
|
||||||
(with-open [conn (db/connection)]
|
(with-open [conn (db/connection)]
|
||||||
(delete-image conn params)))
|
(sc/apply-atomic conn delete-image params)))
|
||||||
|
|
||||||
;; --- List Images
|
;; --- List Images
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue