使用C#与ChromeDriver处理无标识文件上传按钮的JS执行问题
解决无ID/Name属性的JS页面文件上传问题
问题背景
页面完全由JavaScript构建,上传按钮无ID或name属性,尝试的C#代码无法生效,ChromeDriver提示element not intractable,无法设置document.forms[0].file_1.value的值。
尝试的代码:
myField = driver.FindElement(By.XPath("//input[@name='document.forms[0].file_1.value']")); myField.SendKeys(String.Format("{0}{1}", gPath, "COMPLETEPETITION.pdf"));
页面关联的JavaScript函数:
function transfer_attach() { var files = ""; var filename = getfilename(); var items = document.forms[0].files.length; var error = 0; if(items == 0) { if(filename == "") { alert("You must specify the name of the PDF attachment and add it to the list."); return 0; } else { error = 1; } } if(!error) { for (var i = 0; i < items ; i++) { if(document.forms[0].files.options[i].text != "") { if(files == "") { files = document.forms[0].files.options[i].value; } else { files = files + "," + document.forms[0].files.options[i].value; } } } if(i == 0){ document.forms[0].Action.value = "sendone"; }else{ document.forms[0].FileList.value = files; } } if(filename != "" && document.forms[0].Action.value == "sendall") { error = 1; } // remind the user to add document to the list if(error) { alert("Please add to the list."); return 0; } return 1; }
页面截图:
解决方案
1. 定位隐藏的原生文件输入元素
多数JS构建的上传按钮,实际触发的是隐藏的<input type="file">元素,可按以下步骤处理:
- 用XPath定位表单内的file类型输入:
By.XPath("//form//input[@type='file']") - 若元素隐藏,先通过JS使其可见,再执行
SendKeys:
IWebElement fileInput = driver.FindElement(By.XPath("//form//input[@type='file']")); // 执行JS显示元素 ((IJavaScriptExecutor)driver).ExecuteScript("arguments[0].style.display = 'block';", fileInput); fileInput.SendKeys(Path.Combine(gPath, "COMPLETEPETITION.pdf"));
2. 直接调用页面JS函数完成文件添加
从transfer_attach函数逻辑可知,页面会将文件添加到document.forms[0].files下拉列表,再通过FileList提交,可直接构造JS调用:
string filePath = Path.Combine(gPath, "COMPLETEPETITION.pdf"); // 覆盖getfilename函数返回目标文件名 ((IJavaScriptExecutor)driver).ExecuteScript($"window.getfilename = function() {{ return '{Path.GetFileName(filePath)}'; }};"); // 向files下拉列表添加文件选项 ((IJavaScriptExecutor)driver).ExecuteScript(@" var option = document.createElement('option'); option.text = '" + Path.GetFileName(filePath) + @"'; option.value = '" + filePath + @"'; document.forms[0].files.add(option); "); // 调用transfer_attach验证并设置提交参数 bool isValid = (bool)((IJavaScriptExecutor)driver).ExecuteScript("return transfer_attach();"); if(isValid) { // 提交表单 driver.FindElement(By.XPath("//form")).Submit(); }
3. 配合显式等待确保元素可交互
确保目标元素处于可见、可点击状态,使用显式等待避免元素未加载完成的问题:
WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10)); IWebElement fileInput = wait.Until(ExpectedConditions.ElementToBeClickable(By.XPath("//form//input[@type='file']"))); fileInput.SendKeys(Path.Combine(gPath, "COMPLETEPETITION.pdf"));
内容的提问来源于stack exchange,提问作者Deek880
相关产品推荐
相关产品推荐

