如何在没有文本框的情况下使用Selenium上传文件

10

我一直在寻找Selenium 2中上传文件的解决方案。

问题在于我要上传的网络元素有两种使用方式:拖放或点击按钮。没有输入框。并非我没有尝试使用sendKeys。我已经在按钮和所有周围的元素上尝试过了。

这个问题的第二部分是,我是在Windows机器上编写代码,但自动化操作是在Linux机器上进行的。这意味着AutoIt将无法使用。这是上传框的HTML代码。

<div class="up-target" id="up-drop-zone">
    <div class="up-drop-zone-pre hidden">
        <p>Please choose a folder to upload</p>
    </div>
    <div class="up-drop-zone-decor">
        <p>Drop one or more files here</p>
        <p>or</p>
        <button name="uploadFile" class="upload">Select Files</button>
        <input type="file" id="up-drop-zone-input" name="files[]" multiple="true">
    </div>
</div>

我正在使用Java,并且开放接受Selenium以外的其他方法(但是,我只有选定的Maven存储库)。

谢谢!

4个回答

9

很遗憾,目前(2013年1月,Selenium 2.29.1),无法这样做,因为Selenium不支持<input type="file" multiple>元素。

项目开发人员自己提出了此功能增强请求,但尚未实现。您可以在那里将其标记为重点以提高优先级。

此外,据我所知,您无法可靠地从桌面拖动文件到WebElement

解决方法可能是使用AutoIT(仅适用于Windows)或{{link3:Robot}}类(也仅适用于与您的设置类似的设置),并“盲目”输入对话框中的路径:

driver.findElement(By.id("up-drop-zone-input")).click();
Robot r = new Robot();
r.keyPress(KeyEvent.VK_C);        // C
r.keyRelease(KeyEvent.VK_C);
r.keyPress(KeyEvent.VK_COLON);    // : (colon)
r.keyRelease(KeyEvent.VK_COLON);
r.keyPress(KeyEvent.VK_SLASH);    // / (slash)
r.keyRelease(KeyEvent.VK_SLASH);
// etc. for the whole file path

r.keyPress(KeyEvent.VK_ENTER);    // confirm by pressing Enter in the end
r.keyRelease(KeyEvent.VK_ENTER);

很遗憾,但它应该能够工作。请注意,您可能需要这些内容:如何使机器人键入“:”?将字符串转换为KeyEvents(此外还有新的和闪亮的{{link3:KeyEvent#getExtendedKeyCodeForChar()}},它可以完成类似的工作,但仅在JDK7中可用)。


可以了。我可以获取任何机器的本地文件路径,所以将字符串转换为KeyEvents链接非常有用。谢谢! - Nathan Merrill

1
我发现唯一能让它正常工作的方法是使用AutoIt(感谢LittlePandauser3903359的答案)。
我改进了脚本,因为我发现在测试运行时执行任何其他操作都可能导致它停止工作。诀窍是找到窗口,然后激活它才能输入文本。
超时是为了防止多个AutoIt脚本挂在后台,这意味着当你停止测试并尝试做自己的工作时,它们会开始打字!
请注意,在不同的浏览器中窗口的名称不同(例如在Chrome中为“打开”)。
$windowHandle = WinWait("Choose File to Upload", "", 3) ; 3 second timeout - NB the window name will be different in different browsers!

If $windowHandle == 0 Then
   MsgBox(0, "", "Upload popup not found")
Else
   ;MsgBox(0, "", "Upload popup found: " & $windowHandle)
   WinActivate($windowHandle)
   Send("C:\\path\to\myfile.txt")
   Send("{ENTER}")
EndIf

我假设从Java运行AutoIt脚本与其他答案相同:

Runtime.getRuntime().exec("MyAutoItScript.exe");

在C#中运行AutoIt脚本:
var process = Process.Start(@"C:\\path\to\myAutoItScript.exe");
process.WaitForExit();
Thread.Sleep(200); // IE fix for Modal dialog present exception

0

试试这样做

driver.findElement(By.id("up-drop-zone-input")).sendKeys("filePath");

我已经尝试过了。在任何这些元素上使用sendKeys都不起作用。它只是一个不接受文本的按钮。 - Nathan Merrill
那实际上不是按钮,而是文件类型的输入标签。它应该可以使用sendKeys方法来操作。 - Santoshsarma
2
我无法让它正常工作。在Selenium中通常可以,但在我的特定情况下却不行。 - Nathan Merrill

0

我以为autoIT会解决问题,只是我的测试中Java代码的一部分

String[] commands = new String[]{};
commands = new String[]{"c:/test/attachFile.exe"};
Runtime.getRuntime().exec(commands);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接