Как отправить входной поток в качестве ответа в кольце?

У меня есть следующий код, в котором я хочу отправить InputStream файла в функцию fetch-items, которая обрабатывает элементы маршрута /fetch.

(defn id->image [image-id]
    (let [image (.getInputStream (gfs/find-by-id fs image-id))] image))

(defn item-resp [item]
  (assoc item :_id (str (:_id item))
         :images (into [] (map id->image (:image-ids item))))
  )

(defn fetch-items [req]
  (res/response 
   (map item-resp (find fs "items" {}))))

Вот мой запрос на стороне клиента с использованием cljs-ajax:

   (ajax-request
    {:uri "http://localhost:5000/fetch-items"
     :method :get
     :handler #(prn (into [] %))
     :format (json-request-format)
     :response-format (raw-response-format)
     }
    )

Но ответ, который я получаю от клиента, таков:

[:failure :parse] [:response nil] [:status-text "No reader function for tag object.  Format should have been EDN"]
:original-text "{:_id \"5e63f5c591585c30985793cd\", :images [#object[com.mongodb.gridfs.GridFSDBFile$GridFSInputStream 0x22556652 \"com.mongodb.gridfs.GridFSDBFile$GridFSInputStream@22556652\"]]}{:_id \"5e63f5d891585c30985793d0\", :images [#object[com.mongodb.gridfs.GridFSDBFile$GridFSInputStream 0x266ae6c0 \"com.mongodb.gridfs.GridFSDBFile$GridFSInputStream@266ae6c0\"]]}{:_id \"5e63f5e891585c30985793d3\", ...

Почему в ответе говорится, что формат должен быть edn? Как извлечь этот файл/изображение на стороне клиента?

--- РЕДАКТИРОВАТЬ ----

Делаем следующее:

(IOUtils/toString image "utf-8")

возвращает строку размером 1594 байта, что намного меньше ожидаемого размера изображения. Я думаю, это потому, что он преобразует объект файла в base64, а не фактический блок данных, связанный с ним. экземпляр базы данных

Как мне заставить его преобразовать фактический фрагмент GridFS в строку base64, а не в файловый объект?


person zengod    schedule 07.03.2020    source источник


Ответы (1)


Кажется, что вы строите ответ и напрямую помещаете ссылку на объект InputStream в ответ, не кодируя содержимое потока в массив байтов и не сериализуя содержимое в ответе.

Вам нужно будет найти способ прочитать содержимое потока и закодировать его в ответе (может быть, отправить их в кодировке base 64?)

С другой стороны, клиент, кажется, ожидает ответа EDN, и когда он находит строку #object, он пожаловался, что не может прочитать объект с таким тегом.

Вот простой пример того, как читать строку EDN с помеченным литералом, вы можете расширить его, чтобы декодировать изображение в клиенте (обратите внимание, что я использую Java в декодере, вам понадобится другая реализация на JS):

(defn b64decode [s]
  (->> s .getBytes (.decode (java.util.Base64/getDecoder)) String.))

(def message "{:hello :world :msg #base64str \"SGV5LCBpdCB3b3JrcyE=\"}")

;; Now we can read the EDN string above adding our handler for #base64str

(clojure.edn/read-string {:readers {'base64str b64decode}} message)
;; => {:hello :world, :msg "Hey, it works!"}


person Denis Fuenzalida    schedule 07.03.2020
comment
Какой быстрый способ преобразовать InputStream в строку base64? - person zengod; 08.03.2020
comment
Проверьте это: gist.github.com/dfuenzalida/cb5056bfa0743200f787185d3275026e - person Denis Fuenzalida; 08.03.2020
comment
Ни код ссылки, ни (IOUtils/toString my-input-stream utf-8), похоже, не работают для GridFSDBInputStream, поскольку я получаю одну и ту же строку base64 для каждого файла в обоих случаях, а также недостаточно длинна для изображения. - person zengod; 08.03.2020
comment
В вашем примере кода функция id->image кажется неполной. Проверьте, действительно ли вы изменили его на slurp содержимое InputStream, и используйте count, чтобы определить, насколько он велик, как вы ожидаете. - person Denis Fuenzalida; 08.03.2020
comment
Похоже, что все эти методы преобразуют объект файла в base64, а не фактический блок gridfs, связанный с объектом файла. Проверьте редактирование для деталей. - person zengod; 08.03.2020
comment
Мне кажется проблема все-таки в функции id->image. Вместо того, чтобы возвращать InputSteam, прочитайте его содержимое с помощью slurp и посмотрите, что там (может быть, вы можете проверить это на REPL). Я не знаком с драйвером monger, но может быть, InputStream содержит данные, уже закодированные в BSON? - person Denis Fuenzalida; 08.03.2020