Since it’s been a while since my last Selenium tips blog post, I thought it was time to share some Selenium love again. Today we’re covering WebDriver’s native solution to a very common issue when doing distributed cross browser testing: uploading files in remote servers.
As you may know, the way to address this in Selenium 1 is to place your files in an accessible web server and use the attachFile command that points to the correct URL. With Selenium 2, the Selenium Dev team has luckily made this a lot more straightforward.
For those of you doing this locally, all you need to do is use the sendKeys command to type the local path of the file in any file field. This works like a charm in all drivers. When moving this test to a remote server (such as, for example, our Selenium 2 Cloud), all you need to do is use the setFileDetector method to let WebDriver know that you’re uploading files from your local computer to a remote server instead of just typing a path. Almost magically, the file will be base64 encoded and sent transparently through the JSONWireProtocol for you before writing the fixed remote path. This is an excellent solution, as it lets you switch your tests from a local to remote Driver without having to worry about changing your tests’ code.
This feature is available in all the official Selenium 2 bindings, just make sure Selenium 2.8.0 or newer is used as this feature has been released then. Here are some examples tests:
Java
Ruby
And here’s what the test looks like after running in our cloud:
https://saucelabs.com/jobs/1a408cf60af0601f49052f66fa37812c
Pro tip: Write your own FileHandler that will use special codes to represent files before typing paths (locally) or uploading them (remotely). Example: “test-file:small-image”

Thanks for the sum-up. Could you please explain why Selenium 2.8.0 or _older_?
You say Selenium 2.8.0 or older, but the code specifies version 2.18.0 in the DesiredCapabilities. Which is correct?
I’ve tried this, and gotten nothing but UnsupportedCommandExceptions from the sendKeys method. Is there a way around this?
Is this working in IE7 (in saucelabs)?
I was able to get this to work in FireFox 3.6
IE7 just times out sending the file.
You showed how to use LocalFileDetector and you also mentioned using the FileHandler class that “lets you switch your tests from a local to remote Driver without having to worry about changing your tests’ code”.
That would be great, but could you please give an example on how to use FileHandler.
I’m also interested in the answers on the questions:
- Does this only work on Selenium 2.0.8 and older? (Shouldn’t this be “newer”?)
- And you mention the “FileHandler” class for remote driver usage, but without an example on how to use it. Can you please give a remote example?
Thanks for pointing out the error. This only works on 2.8.0 or “newer”.
The FileHandler class was also a typo, this should have been FileDetector. The blog post shares all the information that you need to know to make this happen both locally, in a grid or in our service.
What’s the JSONWireProtocol equivalent of this command?
The reason that I ask is that I’m trying to do this with PHP, and I can’t seem to find any documentation on any PHP library to do this.
[...] resources) on how to remotely upload files on Selenium WebDriver via PHP. I’ve read this http://saucelabs.com/blog/index.php/2012/03/selenium-tips-uploading-files-in-remote-webdriver/, and it mentions that you need to use a “setFileDetector” method somehow to change the [...]
[...] Uploading Files in Remote WebDriver showcases part of the Remote WebDriver stuff that doesn’t get much written about it. [...]
I’m working with the maintainer of the Perl interface to Selenium 2 (i.e. Selenium::Remote::Driver, https://github.com/aivaturi/Selenium-Remote-Driver) to implement this feature — file upload to the selenium host. But it is an obstacle that the session/:sessionId/file request is not documented anywhere.
[...] Selenium Tips: Uploading Files in Remote WebDriver [...]
I would like to point out that the following Selenium group discussion thread has the latest info on doing file uploads over RemoteWebDriver correctly than this earlier blog post.
http://groups.google.com/forum/#!topic/webdriver/OU2RxvTE7UY/discussion
Ivan, Nikko, and others, I guess at this point w/o proper JSONWireProtocol documentation, the best way to implement for other (unofficial) language bindings is to reverse engineer the implementation by network traffic sniffing what happens when you do the file upload w/ RemoteWebDriver in Java. Only then can we see what the JSONWireProtocol request & response looks like.
I’m also assuming the file is transferred from Selenium code machine to remote/grid node as base64 encoded content, since profiles and extensions are base64 encoded transferred.
Is there a way to do this in python? It seems like the setFileDetector stuff is missing in the Python bindings.
Hi,
Thank you very much, this helped me a lot
Happy to hear that, Veni
Any info on the JSONWireProtocol equivalent? I’m trying to implement a file upload w/ RemoteWebDriver using WebDriverJS
Jeff, probably the most detailed guide is the source code in other client bindings:
https://github.com/SeleniumHQ/selenium/blob/master/py/selenium/webdriver/remote/webelement.py#L144-L149
It basically uploads the file via a special api, pulls the new path, types that new path in the file field.