在实际工作中,我们进行web自动化的时候,文件上传是很常见的操作,例如上传用户头像,上传身份证信息等。所以宏哥打算按上传文件的分类对其进行一下讲解和分享。
想必小伙伴们或者童鞋们一定很好奇,既然上传文件在自动化这么常见而且经常用到,那么为什么Selenium的webdriver为什么不提供方法(API),宏哥这里解释一下原因:因为上传文件需要打开window窗口,webdriver是无法对window的控件操作的,换句话说就是:selenium无法识别非web的控件,上传文件窗口为系统自带,无法识别窗口元素。所以没有提供方法,需要我们换个思路去上传文件。
首先,我们要区分出上传按钮的种类,大体上可以分为两种,一种是input框,另外一种就比较复杂,通过js、flash等实现,标签非input。
上传文件有两种场景:input控制上传和非input控件上传。大多数情况都是input控件上传文件,只有非常少数的使用自定义的非input上传文件。今天宏哥这一篇文章就用来介绍非input控件上传文件。
非input控件上传文件,我们要引入外部插件上传。这种上传千奇百怪,有用a标签的,有用div的,有用button的,有用object的,我们没有办法通过直接在网页上处理掉这些上传,唯一的办法就是打开OS弹框,去处理弹框。有两种方法一种通过pywin32上传(这种只支持python语言),另一种是通过autoit上传(python和java都支持,其他的没有实践过)。这里我们只会讲到autoit上传文件。
宏哥总结了一下,大体上有以下几种解决方案:
(1)autoIT,借助外力,我们去调用其生成的au3或exe文件。
(2)Python pywin32库,识别对话框句柄,进而操作
(3)SendKeys库
(4)keybd_event,跟3类似,不过是模拟按键,ctrl+a,ctrl+c, ctrl+v…
介绍纯Java的方式去处理,web上本地上传图片的功能。这个过程,我们还是需要用到Robot这个类,由于在web上点击了本地上传图片后,弹出的框很特殊,selenium无法识别这个弹窗,所以在selnium中没有直接的方法去实现上传本地文件。
其实也是上边提到的第四种解决方案,模拟键盘操作。宏哥利用Robot的大致流程是这样的:
1.用selnium点击web上本地上传文件的按钮
2.在弹窗,文件路径输入框默认是光标聚焦,我们把文件在磁盘上的路径,通过拷贝和黏贴方法写上去。
3.通过按下回车站,默认触发弹窗的确定按钮,完成了文件上传过程。
打开百度首页,搜索按钮左侧有一个照相机的图标,点击可以选择图片搜索,我们通过本地上传图片的过程来模拟文件自动化上传操作,上传成功后,百度识图会识别是不是百度搜索的图片,如果是,就会显示图片的信息,如果不是,就会识别失败,提示重新上传。准备条件,你在百度图片搜索一个图片,保存到你桌面,例如宏哥找到一个关于selenium的图片,然后保存在桌面的test文件夹,名称为北京宏哥的拼音首字母:bjhg.jpeg。
package lessons;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.datatransfer.StringSelection;
import java.awt.event.KeyEvent;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
/**
* @author 北京-宏哥
*
* @公众号:北京宏哥
*
* @《手把手教你》系列技巧篇(五十三)-java+ selenium自动化测试-上传文件-中篇(详细教程)
*
* @2021年12月12日
*/
public class FileUpload {
public static void main(String[] args) throws Exception {
System.setProperty("webdriver.gecko.driver",".\\Tools\\geckodriver.exe");
WebDriver driver = new FirefoxDriver();
driver.manage().window().maximize();
driver.get("https://www.baidu.com");
// 指定图片的路径,这里我放桌面上
StringSelection sel = new StringSelection(
"C:\\Users\\DELL\\Desktop\\test\\bjhg.jpeg");
// 把图片文件路径复制到剪贴板
Toolkit.getDefaultToolkit().getSystemClipboard().setContents(sel, null);
System.out.println("selection" + sel);
// 点击照相机这个按钮
driver.findElement(By.xpath("//*/span[@class='soutu-btn']")).click();
// 点击本地上传图片
driver.findElement(By.xpath("//*/input[@class='upload-pic']")).click();
// 新建一个Robot类的对象
Robot robot = new Robot();
Thread.sleep(1000);
// 按下回车
robot.keyPress(KeyEvent.VK_ENTER);
// 释放回车
robot.keyRelease(KeyEvent.VK_ENTER);
// 按下 CTRL+V
robot.keyPress(KeyEvent.VK_CONTROL);
robot.keyPress(KeyEvent.VK_V);
// 释放 CTRL+V
robot.keyRelease(KeyEvent.VK_CONTROL);
robot.keyRelease(KeyEvent.VK_V);
Thread.sleep(1000);
// 点击回车 Enter
robot.keyPress(KeyEvent.VK_ENTER);
robot.keyRelease(KeyEvent.VK_ENTER);
Thread.sleep(5000);
System.out.println("browser will be close");
driver.quit();
}
}
1.运行代码,右键Run AS->Java Appliance,控制台输出,如下图所示:
2.运行代码后电脑端的浏览器的动作,如下小视频所示:
奇怪了,细心地小伙伴或者童鞋们。一定会发现宏哥之前的代码都是用火狐浏览器,结果录制的视频却是Chrome浏览器,原因是:开始Chrome浏览器不可以模拟成功,宏哥就换了Firefox浏览器成功了,第二天宏哥抱着试一下的心理,结果也成功了。但是原因没有找到,开始宏哥以为是Chrome浏览器版本高,而宏哥的Firefox是一个低版本的,所以换了Firefox,但是Chrome今天可以成功,那就不是版本问题,而且宏哥怀疑是图片的名字中英文,但是试过了也是没有关系的。但是宏哥还是提醒各位最好用英文的。实在找不到原因了,有知道可以留言宏哥哦!!! 好了,今天时间也不是很早了,宏哥今天就讲解和分享到这里,感谢您耐心的阅读,下一篇讲解借助工具来处理非input控件上传文件。