Last active
April 15, 2025 07:41
-
-
Save florentbr/349b1ab024ca9f3de56e6bf8af2ac69e to your computer and use it in GitHub Desktop.
Selenium - Drop a file from the desktop on a drop area
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from selenium import webdriver | |
from selenium.webdriver.remote.webelement import WebElement | |
import os.path | |
# JavaScript: HTML5 File drop | |
# source : https://gist.github.com/florentbr/0eff8b785e85e93ecc3ce500169bd676 | |
# param1 WebElement : Drop area element | |
# param2 Double : Optional - Drop offset x relative to the top/left corner of the drop area. Center if 0. | |
# param3 Double : Optional - Drop offset y relative to the top/left corner of the drop area. Center if 0. | |
# return WebElement : File input | |
JS_DROP_FILES = "var k=arguments,d=k[0],g=k[1],c=k[2],m=d.ownerDocument||document;for(var e=0;;){var f=d.getBoundingClientRect(),b=f.left+(g||(f.width/2)),a=f.top+(c||(f.height/2)),h=m.elementFromPoint(b,a);if(h&&d.contains(h)){break}if(++e>1){var j=new Error('Element not interactable');j.code=15;throw j}d.scrollIntoView({behavior:'instant',block:'center',inline:'center'})}var l=m.createElement('INPUT');l.setAttribute('type','file');l.setAttribute('multiple','');l.setAttribute('style','position:fixed;z-index:2147483647;left:0;top:0;');l.onchange=function(q){l.parentElement.removeChild(l);q.stopPropagation();var r={constructor:DataTransfer,effectAllowed:'all',dropEffect:'none',types:['Files'],files:l.files,setData:function u(){},getData:function o(){},clearData:function s(){},setDragImage:function i(){}};if(window.DataTransferItemList){r.items=Object.setPrototypeOf(Array.prototype.map.call(l.files,function(x){return{constructor:DataTransferItem,kind:'file',type:x.type,getAsFile:function v(){return x},getAsString:function y(A){var z=new FileReader();z.onload=function(B){A(B.target.result)};z.readAsText(x)},webkitGetAsEntry:function w(){return{constructor:FileSystemFileEntry,name:x.name,fullPath:'/'+x.name,isFile:true,isDirectory:false,file:function z(A){A(x)}}}}}),{constructor:DataTransferItemList,add:function t(){},clear:function p(){},remove:function n(){}})}['dragenter','dragover','drop'].forEach(function(v){var w=m.createEvent('DragEvent');w.initMouseEvent(v,true,true,m.defaultView,0,0,0,b,a,false,false,false,false,0,null);Object.setPrototypeOf(w,null);w.dataTransfer=r;Object.setPrototypeOf(w,DragEvent.prototype);h.dispatchEvent(w)})};m.documentElement.appendChild(l);l.getBoundingClientRect();return l" | |
def drop_files(element, files, offsetX=0, offsetY=0): | |
driver = element.parent | |
isLocal = not driver._is_remote or '127.0.0.1' in driver.command_executor._url | |
paths = [] | |
# ensure files are present, and upload to the remote server if session is remote | |
for file in (files if isinstance(files, list) else [files]) : | |
if not os.path.isfile(file) : | |
raise FileNotFoundError(file) | |
paths.append(file if isLocal else element._upload(file)) | |
value = '\n'.join(paths) | |
elm_input = driver.execute_script(JS_DROP_FILES, element, offsetX, offsetY) | |
elm_input._execute('sendKeysToElement', {'value': [value], 'text': value}) | |
WebElement.drop_files = drop_files | |
############################# USAGE EXAMPLE ############################# | |
driver = webdriver.Chrome() | |
driver.get("https://react-dropzone.js.org/") | |
dropzone = driver.find_element_by_css_selector("[data-preview='Basic example'] [style]") | |
# drop a single file | |
dropzone.drop_files("C:\\temp\\image1.png") | |
# drop two files | |
dropzone.drop_files(["C:\\temp\\image1.png", "C:\\temp\\image2.png"]) | |
# drop a file by offset | |
dropzone.drop_files("C:\\temp\\image1.png", offsetX=25, offsetY=25) | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var args = arguments, | |
element = args[0], | |
offsetX = args[1], | |
offsetY = args[2], | |
doc = element.ownerDocument || document; | |
for (var i = 0; ;) { | |
var box = element.getBoundingClientRect(), | |
clientX = box.left + (offsetX || (box.width / 2)), | |
clientY = box.top + (offsetY || (box.height / 2)), | |
target = doc.elementFromPoint(clientX, clientY); | |
if (target && element.contains(target)) | |
break; | |
if (++i > 1) { | |
var ex = new Error('Element not interactable'); | |
ex.code = 15; | |
throw ex; | |
} | |
element.scrollIntoView({behavior: 'instant', block: 'center', inline: 'center'}); | |
} | |
var input = doc.createElement('INPUT'); | |
input.setAttribute('type', 'file'); | |
input.setAttribute('multiple', ''); | |
input.setAttribute('style', 'position:fixed;z-index:2147483647;left:0;top:0;'); | |
input.onchange = function (ev) { | |
input.parentElement.removeChild(input); | |
ev.stopPropagation(); | |
var dataTransfer = { | |
constructor : DataTransfer, | |
effectAllowed : 'all', | |
dropEffect : 'none', | |
types : [ 'Files' ], | |
files : input.files, | |
setData : function setData(){}, | |
getData : function getData(){}, | |
clearData : function clearData(){}, | |
setDragImage : function setDragImage(){} | |
}; | |
if (window.DataTransferItemList) { | |
dataTransfer.items = Object.setPrototypeOf(Array.prototype.map.call(input.files, function(f) { | |
return { | |
constructor : DataTransferItem, | |
kind : 'file', | |
type : f.type, | |
getAsFile : function getAsFile () { return f }, | |
getAsString : function getAsString (callback) { | |
var reader = new FileReader(); | |
reader.onload = function(ev) { callback(ev.target.result) }; | |
reader.readAsText(f); | |
}, | |
webkitGetAsEntry : function webkitGetAsEntry () { | |
return { | |
constructor : FileSystemFileEntry, | |
name : f.name, | |
fullPath : '/' + f.name, | |
isFile : true, | |
isDirectory : false, | |
file : function file (callback) { callback(f) } | |
} | |
} | |
} | |
}), { | |
constructor : DataTransferItemList, | |
add : function add(){}, | |
clear : function clear(){}, | |
remove : function remove(){} | |
}); | |
} | |
['dragenter', 'dragover', 'drop'].forEach(function (type) { | |
var event = doc.createEvent('DragEvent'); | |
event.initMouseEvent(type, true, true, doc.defaultView, 0, 0, 0, clientX, clientY, false, false, false, false, 0, null); | |
Object.setPrototypeOf(event, null); | |
event.dataTransfer = dataTransfer; | |
Object.setPrototypeOf(event, DragEvent.prototype); | |
target.dispatchEvent(event); | |
}); | |
}; | |
doc.documentElement.appendChild(input); | |
input.getBoundingClientRect(); /* force reflow for Firefox */ | |
return input; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var k=arguments,d=k[0],g=k[1],c=k[2],m=d.ownerDocument||document;for(var e=0;;){var f=d.getBoundingClientRect(),b=f.left+(g||(f.width/2)),a=f.top+(c||(f.height/2)),h=m.elementFromPoint(b,a);if(h&&d.contains(h)){break}if(++e>1){var j=new Error('Element not interactable');j.code=15;throw j}d.scrollIntoView({behavior:'instant',block:'center',inline:'center'})}var l=m.createElement('INPUT');l.setAttribute('type','file');l.setAttribute('multiple','');l.setAttribute('style','position:fixed;z-index:2147483647;left:0;top:0;');l.onchange=function(q){l.parentElement.removeChild(l);q.stopPropagation();var r={constructor:DataTransfer,effectAllowed:'all',dropEffect:'none',types:['Files'],files:l.files,setData:function u(){},getData:function o(){},clearData:function s(){},setDragImage:function i(){}};if(window.DataTransferItemList){r.items=Object.setPrototypeOf(Array.prototype.map.call(l.files,function(x){return{constructor:DataTransferItem,kind:'file',type:x.type,getAsFile:function v(){return x},getAsString:function y(A){var z=new FileReader();z.onload=function(B){A(B.target.result)};z.readAsText(x)},webkitGetAsEntry:function w(){return{constructor:FileSystemFileEntry,name:x.name,fullPath:'/'+x.name,isFile:true,isDirectory:false,file:function z(A){A(x)}}}}}),{constructor:DataTransferItemList,add:function t(){},clear:function p(){},remove:function n(){}})}['dragenter','dragover','drop'].forEach(function(v){var w=m.createEvent('DragEvent');w.initMouseEvent(v,true,true,m.defaultView,0,0,0,b,a,false,false,false,false,0,null);Object.setPrototypeOf(w,null);w.dataTransfer=r;Object.setPrototypeOf(w,DragEvent.prototype);h.dispatchEvent(w)})};m.documentElement.appendChild(l);l.getBoundingClientRect();return l | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I confirm what @realgt stated, this script is not working anymore with Chrome > 134. And the solution he provided works fine.
Thank you @realgt .