无法使用send_keys在Selenium Webdriver中上传文件

4 投票
2 回答
6253 浏览
提问于 2025-04-18 10:54

我在用Python的Selenium Webdriver做文件上传时遇到了一些麻烦。昨天我重新安装了selenium和python,所以我觉得一切都更新到了最新版本,我用的是Windows 7。如果这有帮助的话。我知道其他人也问过这个问题,大家推荐的答案是使用send_keys命令来处理文件上传的元素。

我在其他网页上尝试过这个方法,至少在一个页面上成功了,但在我现在测试的页面上,照样操作却没有任何反应。我记得看到过其他人也遇到过类似的问题,所以我觉得我不是唯一一个有这个困扰的人。

有一个可能相关的事情是,最开始我在文件上传表单上使用send_keys时,selenium报了一个错误,说这个元素不可见,因此无法进行操作(实际上它是可见的,但在selenium看来却不是)。我通过先运行这段JavaScript代码解决了这个问题:

document.getElementById('UploadDocumentPopup').style.display = 'block';

(UploadDocumentPopup是文件输入部分的父元素)

还有一个可能有用的信息是,当我使用Selenium 1 / Selenium RC时,使用attach_file命令成功上传了文件(不过这个命令只支持Firefox)。

如果有帮助的话,这里是我正在处理的页面的链接。请点击这个链接:https://qa.infosnap.com/family6/gosnap.aspx?action=3345&culture=en,然后点击“继续你的工作”,用邮箱aaaa@b.com和密码“asdfjkl;”(不带引号)登录。接着点击其中一个“继续你的工作”的链接。你应该能看到文件上传和照片上传的部分。如果没有,就用“prev”和“next”按钮翻翻,找到有这些功能的页面(总共就大约3个页面)。这是我认为“应该”能工作的相关代码——我还尝试了很多其他方法,如果有帮助的话我可以分享,但这就是我认为的正确做法。如果你愿意,可以查看页面源代码,顺便告诉你,'documentfile'是页面源代码中input type='file'元素的名称,最后一行的xpath指向的是“上传”按钮。

js = "document.getElementById('UploadDocumentPopup').style.display = 'block';"
wd.execute_script(js)
wd.find_element_by_link_text("Upload Document...").click()
wd.find_element_by_id("documentfile").send_keys("C:\\Users\\username\\testdoc.rtf")
#ActionChains(wd).send_keys(Keys.ESCAPE)
wd.find_element_by_xpath("//div[@id='modal_container']/div/form/div/input[1]").click()

更新:我意识到我只在Firefox上尝试过这个,所以我试了IE11——结果是,当调用send_keys时,系统的文件上传框弹出来了(我觉得这很奇怪,因为我并没有点击“浏览”按钮,只是用了send_keys),然后文件名字段里填入了文本。接着文件上传对话框消失了,但就好像什么都没发生一样。总结一下:在Internet Explorer中,文件上传对话框打开,文件路径被输入到这个对话框中,之后对话框消失,但文件并没有真正附加上。在Firefox中,没有对话框打开,文件也没有附加上。Chrome的情况和Firefox一样。

编辑:这是文件上传部分的HTML代码:

<div id="UploadDocumentPopup" style="display:none;">
    <div class="popupmenu">
        <h1 style="margin-top:0px; padding-bottom:10px; border-bottom:1px solid #CCCCCC;">
            Upload Document
        </h1>
        <p>
            Choose a file to upload.
        </p>
        <form id="documentuploadform" action="services/documentservice.aspx" enctype="multipart/form-data" method="post"
            onsubmit="return AIM.submit(this, {'onStart' : startUploadDocument, 'onComplete' : completeUploadDocument})">
            <input type="file" size="50" id="documentfile" name="documentfile" />
            <input type="hidden" name="cmd" value="upload" />
            <input type="hidden" id="documentuploadfield" name="field" />
            <div style="margin-top: 10px;">
                <input name="ctl00$OutsideFormContentPlaceholder$ctl06" type="submit" value="Upload" />
                <input name="ctl00$OutsideFormContentPlaceholder$ctl07" type="button" onclick="Control.Modal.close();" value="Cancel" />
            </div>
        </form>
    </div>
</div>

我还想提一下,我在寻找一个完全基于selenium的解决方案——我知道AutoIt和类似的工具,但我需要远程运行这个。

2 个回答

0

要找到一个标签为input且类型为'file'的网页元素,可以使用下面的xpath:

//input[@type='file']

在你的情况下,这个元素叫做"documentfile"。

接下来,使用JavaScript让它变得可见:

document.getElementById("documentfile").style.visibility = "visible";

然后,向上面这个输入框发送一个绝对路径的文件名:

driver.findElement(By.xpath("//input[@type='file']")).sendKeys("/absolute/filepath.jpeg");


如果有任何问题,请告诉我。

1

我需要看看整个脚本才能确认代码是否正确,但这段代码应该能给你一些帮助:

wd.find_element_by_css_selector('a[onclick*="uploadDocument"]').click()
wd.find_element_by_css_selector('div#UploadDocumentPopup input#documentfile').send_keys(os.getcwd()+"/<filename>")
wd.find_element_by_css_selector('div#UploadDocumentPopup input[value="Upload"]').click()

在这里,你需要把 <filename> 替换成你想上传的文件的确切名称。这段代码使用了 os.getcwd() 来获取当前测试脚本的工作目录,然后把文件名加到这个工作目录的后面,这样就创建了一个通用的路径,能在任何机器上使用,而不是指定一个绝对路径,这样在其他机器上就可能会出错。用这段代码后,你就不需要再用那个JavaScript代码片段了。

我用了CSS选择器,因为我更喜欢它们而不是xpath,如果你想的话,应该能很容易地把它们转换过来。(如果你真的不会,留言告诉我,我可以帮你试试)

撰写回答