How to change download directory in Chrome driver with etaoin
If you ever had to do web browser automation in Clojure, you know of
etaoin. Overall, it’s an excellant
example of what a utility library should look like. Anyway, let’s get to the point.
If you try to use etaoin with Chromium webdriver, and try to save a file
to a specific location of your computer, you are in for a surprise. The
officially recommended way of changing download directory is to pass
:download-dir
parameter while building the driver. Like this -
;; This is buggy.
(require '[etaoin.api :as e])
(def driver (e/chrome {:download-dir "./my/download/dir"}))
Unfortunately, this does not work (at least it did not work for me in Ubuntu
Linux 20.04
, with ChromeDriver 83.0.4103.39
).
After painstackingly glueing information from web, I came up with a function which correctly changes the download directory. As a bonus, the download directory can be changed for the same driver on ad-hoc basis. Take a look -
(require '[etaoin.api :as e])
(defn change-chrome-download-dir
"Changes download directory of chrome web driver."
[driver download-dir]
;; NOTE: Need to do some black magic to circumvent chrome download dir bug.
;; Resources:
;; - https://bugs.chromium.org/p/chromium/issues/detail?id=696481#c164
;; - http://etaoin.grishaev.me/etaoin.api-api.html#etaoin.api/execute
;; - https://selenium.dev/selenium/docs/api/rb/Selenium/WebDriver/Chrome/Bridge.html#send_command-instance_method
(etaoin.api/execute {:driver driver
:method :post
:path [:session (:session @driver) "goog/cdp/execute"]
:data {:cmd "Page.setDownloadBehavior"
:params {:behavior "allow"
:downloadPath download-dir}}}))
(def driver (e/chrome))
(change-chrome-download-dir driver "./my/download/dir")
(e/click driver :download-link-id)
Hope this post saves some of your frustration.