ClojureScript With React Native - File Download

312 views Asked by At

I want to download a file into the phone storage from a mobile application with ClojureScript and react-native. Files are already uploaded to an Amazon S3 bucket. The file URLs would be something like https://s3.amazonaws.com/client-texastech/uploads/art_pictures-images/comma-2005-06/96acad35-7f3f-4b10-a104-5bf59b92b463/medium/image.jpg?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAIQETNIOQ45P7UIKQ%2F20181113%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20181113T023654Z&X-Amz-Expires=300&X-Amz-SignedHeaders=host&X-Amz-Signature=576787721283e1c2b0d8fd2349cd304b5f7f717491edb32d8d7ba256ef52f6a8

I found react-native-fetch-blob for doing it.

I tried to use it:

    (def RNFetchBlob (js/require "react-native-fetch-blob"))
    (def fetch-blob (oget RNFetchBlob "default"))
    (def fs (oget RNFetchBlob "fs"))

      (defn download-url [app-db url]
  (p/promise (fn [resolve reject]
                  (let [fs (oget fetch-blob "fs")
                      dir-path (str (oget (oget fs "dirs") "DocumentDir") "/image.png")
                      fetch-config (ocall fetch-blob "config" {
                                       :addAndroidDownloads {:useDownloadManager true :path dir-path :notification true}
                                       :Cache-Control "no-store"}) 
                      fetch-file (ocall fetch-config "fetch" "GET" url (util/get-token app-db))
                      base64 (oget fetch-blob "base64")]
                  (ocall fetch-file "then" (fn [res]
                      (.log js/console "Download file completed." res)
                      (resolve true)))
                  (ocall fetch-file "catch" (fn [res]
                        (.log js/console "Download file failed" res)
                        (resolve false)))
              #js{:timeout 600000
                  :distanceFilter 1
                  :maximumAge 1000
                  :enableHighAccuracy false}))))

The download completed. But, I can't find the file in any of the folders. Is there anything wrong? If so, can anyone share the code snippet?

2

There are 2 answers

0
Tessy Thomas On BEST ANSWER

Finally, I was able to download the file. The issue is where I pass parameters to the config call. We should convert Clojure to JS by using clj->js. The updated method will be as follows:

(defn download-image-android [app-db url image-id]
  (p/promise (fn [resolve reject]
      (let [fs (oget fetch-blob "fs")
          android-dir-path (str (oget (oget fs "dirs") "DownloadDir") "/" image-id ".jpg")
          params (parse-params url)
          fetch-config (ocall fetch-blob "config" (clj->js {
                            :fileCache true
                            :addAndroidDownloads {:useDownloadManager true :path android-dir-path :notification true}})) 
          fetch-file (ocall fetch-config "fetch" "GET" url (clj->js {:Signature (:X-Amz-Signature params)
                                                                :Cache-Control "no-store"}))]
          (ocall fetch-file "then" (fn [res]
              (show-alert "Success" "Image has been saved to the phone successfully!")
              (resolve true)))
          (ocall fetch-file "catch" (fn [res]
              (show-alert "Error" "Image cannot be downloaded. Please try again!")
              (.log js/console "Download file failed" res)
              (resolve false)))
      #js{:timeout 30000
          :distanceFilter 1
          :maximumAge 1000
          :enableHighAccuracy false}))))
1
Chris Callwait On

If you want to download and show any images form S3 you can use RN Image with source property

 [image {:source "https://your.s3.bucket/path.jpg"}]

If it's just a file then use rn-fetch-blob

(defn fetch-file! [url]
  (let [result (promise-chan)]
    (-> RNFetchBlob
      (.config #js{})
      (.fetch "GET" url)
      (.then #(.text %))
      (.then #(put! result [true %]))
      (.catch #(put! result [false %])))
    result))

Make sure you have access for your S3 file