Automate operations with files
Automate file download
The example shows how to automate the Save File As system dialog. A file is saved by the Desktop driver.
tip
- To save a file on an RPA Node, use the
downloadFileOnAgent(String path)method. - To pass a file from an RPA Node to the Control Tower server, use the
downloadFileFromAgent(String path)method.
Your file is saved into the RPA Agent machine's temporary folder. To upload it on S3, use S3 plugins.
You need to configure an S3 bucket first. To simulate the use of the S3 bucket, refer to Upload files to S3 MinIO Storage.
The preconditions are as follows:
- Local disk D.
temp.bucketas the S3 bucket name or any other name. In the latter case, make the corresponding changes in the script.
Switch to Save As in Chrome and use desktop driver
Expand to view the code
import com.workfusion.bot.service.SecureEntryDTO;
import com.workfusion.odf2.compiler.BotTask;
import com.workfusion.odf2.core.cdi.Requires;
import com.workfusion.odf2.core.task.AdHocTask;
import com.workfusion.odf2.core.task.TaskInput;
import com.workfusion.odf2.core.task.output.TaskRunnerOutput;
import com.workfusion.odf2.core.webharvest.rpa.RpaDriver;
import com.workfusion.odf2.core.webharvest.rpa.RpaFactory;
import com.workfusion.odf2.core.webharvest.rpa.RpaRunner;
import com.workfusion.odf2.service.ControlTowerServicesModule;
import com.workfusion.odf2.service.s3.S3Bucket;
import com.workfusion.odf2.service.s3.S3Service;
import com.workfusion.odf2.service.vault.SecretsVaultService;
import com.workfusion.rpa.driver.Driver;
import com.workfusion.rpa.helpers.RPA;
import com.workfusion.rpa.helpers.UiElement;
import com.workfusion.rpa.helpers.UiElementCollection;
import org.openqa.selenium.Alert;
import org.openqa.selenium.By;
import org.openqa.selenium.Keys;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.Select;
import org.slf4j.Logger;
import javax.inject.Inject;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;
import java.util.List;
import static com.workfusion.rpa.helpers.RPA.*;
import static com.workfusion.rpa.helpers.UiSelectors.*;
@BotTask(requireRpa = true)
@Requires({ControlTowerServicesModule.class})
public class AutomateWebElements implements AdHocTask {
private final RpaRunner rpaRunner;
private final Logger logger;
private final SecretsVaultService secretsVault;
private final S3Service s3Service;
@Inject
public AutomateWebElements(RpaFactory rpaFactory, Logger logger, SecretsVaultService secretsVault ,S3Service s3Service){
this.rpaRunner = rpaFactory
.builder(RpaDriver.UNIVERSAL)
.closeOnCompletion(true)
.build();
this.logger = logger;
this.secretsVault = secretsVault;
this.s3Service = s3Service;
}
@Override
public TaskRunnerOutput run(TaskInput taskInput) {
rpaRunner.execute(driver->{
try {
this.switchToSaveAsInChromeAndUseDesktopDriver(driver);
} catch (AWTException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
});
return taskInput.asResult()
.withColumn("example_bot_task_output", "completed_successfully");
}
private void switchToSaveAsInChromeAndUseDesktopDriver(Driver driver) throws AWTException, IOException {
RPA.pageLoadTimeout(3 * 1000);
try {
RPA.openChrome("https://rpa-tutorial.s3.amazonaws.com/trainings/ie-download.html");
String winhandle = driver.getWindowHandle();
logger.debug(" handle " + winhandle );
$(byPartialLinkText("Portable Zip")).click();
// If click was not performed, try this workaround:
// $(byPartialLinkText('Portable Zip')).sendKeys('').pressEnter()
} catch (org.openqa.selenium.TimeoutException ignored) {}
RPA.sleep(2000);
Robot robot = new Robot();
robot.delay(2000);
robot.keyPress(KeyEvent.VK_CONTROL);
robot.keyPress(KeyEvent.VK_S);
robot.keyRelease(KeyEvent.VK_CONTROL);
robot.keyRelease(KeyEvent.VK_S);
RPA.sleep(1000);
driver.switchTo().window("[CLASS:#32770]");
String tempPath = "D:\\_temp\\";
String uniqueId = UUID.randomUUID() + ".json";
String savePath = tempPath + "FileDownloadExample_" + uniqueId;
$("[CLASS:Edit;INSTANCE:1]").sendKeys(savePath).pressEnter();
RPA.sleep(2000);
byte[] fileToUploadOnS3 = Files.readAllBytes(Paths.get(savePath));
S3Bucket s3Bucket = s3Service.getBucket("36807");
String FileName_= "_r2d2/jsonUpload" + UUID.randomUUID() + ".json";
String URL = s3Bucket.put(fileToUploadOnS3,FileName_).getDirectUrl();
this.logger.debug(" URL - " + URL);
}
}
Download file in Chrome
The implementation does not guarantee correct parallel execution of the script on a single node.
Expand to view the code
<?xml version="1.0" encoding="UTF-8"?>
<config xmlns="http://web-harvest.sourceforge.net/schema/1.0/config" scriptlang="groovy">
<script><![CDATA[
// Set your Chrome default download directory here
downloadDir = 'C:/Users/Your Username/Downloads/'
getLastModifiedFileName = {RemoteWebDriver aDriver, String dirPath ->
return (String) aDriver.executeScript(
" File dir = new File(\"" + dirPath.replace('\\', '/') + "\");\n" +
" File[] files = dir.listFiles();\n" +
" if (files == null || files.length == 0) {\n" +
" return null;\n" +
" }\n" +
"\n" +
" File lastModifiedFile = files[0];\n" +
" for (int i = 1; i < files.length; i++) {\n" +
" if (lastModifiedFile.lastModified() < files[i].lastModified()) {\n" +
" lastModifiedFile = files[i];\n" +
" }\n" +
" }\n" +
"return lastModifiedFile.getAbsolutePath();"
, "GROOVY");
}
getFileContent = {RemoteWebDriver aDriver, String absoluteFilePath ->
Object res = aDriver.executeScript(
"def bytes = new File('" + absoluteFilePath.replace('\\', '/') + "').bytes; \n"
+ "return Base64.getEncoder().encodeToString(bytes);", "GROOVY");
byte[] content = Base64.getDecoder().decode(res.toString());
return content;
}
getDownloadedFile = {RemoteWebDriver desktopDriver, String downloadDir, String latestFilePath ->
String downloadFilePath = getLastModifiedFileName(desktopDriver, downloadDir);
// Wait until new file appears.
int maxCounter = 1000;
boolean downloadStarted = downloadFilePath != null && !downloadFilePath.equals(latestFilePath);
while (!downloadStarted && maxCounter > 0) {
Thread.sleep(10);
downloadFilePath = getLastModifiedFileName(desktopDriver, downloadDir);
downloadStarted = downloadFilePath != null && !downloadFilePath.equals(latestFilePath);
maxCounter--;
}
// Lets wait until latest file is not tmp or crdownload.
if (downloadStarted) {
maxCounter = 300;
downloadFilePath = getLastModifiedFileName(desktopDriver, downloadDir);
String fileExtension = org.apache.commons.io.FilenameUtils.getExtension(downloadFilePath);
boolean isDownloading = "crdownload".equals(fileExtension) || "tmp".equals(fileExtension);
while (isDownloading && maxCounter > 0) {
Thread.sleep(100);
downloadFilePath = getLastModifiedFileName(desktopDriver, downloadDir);
fileExtension = org.apache.commons.io.FilenameUtils.getExtension(downloadFilePath);
isDownloading = "crdownload".equals(fileExtension) || "tmp".equals(fileExtension);
maxCounter--;
}
if (!isDownloading) {
return getFileContent(desktopDriver, downloadFilePath);
}
}
throw new Exception("Some issues during file download");
}
]]></script>
<robotics-flow>
<robot name="desktopDriver" driver="desktop" close-on-completion="false">
<script><![CDATA[
aDriver = driver()
latestFilePath = getLastModifiedFileName(aDriver, downloadDir)
]]></script>
</robot>
<robot name="robotDriver" driver="chrome" close-on-completion="true"
start-in-private="true">
<script><![CDATA[
open('http://wf-sharebox.s3.amazonaws.com/some-cool-video.zip')
documentContent = getDownloadedFile(aDriver, downloadDir, latestFilePath)
]]></script>
</robot>
<script><![CDATA[
try {
aDriver.quit()
} catch(Exception ignore) {}
]]></script>
</robotics-flow>
<!-- Upload to S3 or perform any other actions. -->
<!-- Export your values -->
<export include-original-data="true">
<single-column name="content" value="${documentContent}"></single-column>
</export>
</config>
Automate file upload
Expand to view the code
import com.workfusion.bot.service.SecureEntryDTO;
import com.workfusion.odf2.compiler.BotTask;
import com.workfusion.odf2.core.cdi.Requires;
import com.workfusion.odf2.core.task.AdHocTask;
import com.workfusion.odf2.core.task.TaskInput;
import com.workfusion.odf2.core.task.output.TaskRunnerOutput;
import com.workfusion.odf2.core.webharvest.rpa.RpaDriver;
import com.workfusion.odf2.core.webharvest.rpa.RpaFactory;
import com.workfusion.odf2.core.webharvest.rpa.RpaRunner;
import com.workfusion.odf2.service.ControlTowerServicesModule;
import com.workfusion.odf2.service.vault.SecretsVaultService;
import com.workfusion.rpa.driver.Driver;
import com.workfusion.rpa.helpers.RPA;
import com.workfusion.rpa.helpers.UiElement;
import com.workfusion.rpa.helpers.UiElementCollection;
import org.openqa.selenium.Alert;
import org.openqa.selenium.By;
import org.openqa.selenium.Keys;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.Select;
import org.slf4j.Logger;
import javax.inject.Inject;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import static com.workfusion.rpa.helpers.RPA.*;
import static com.workfusion.rpa.helpers.UiSelectors.byImage;
import static com.workfusion.rpa.helpers.UiSelectors.byText;
@BotTask(requireRpa = true)
@Requires({ControlTowerServicesModule.class})
public class AutomateWebElements implements AdHocTask {
private final RpaRunner rpaRunner;
private final Logger logger;
private final SecretsVaultService secretsVault;
private static final String s3Path = "https://rpa-tutorial.s3.amazonaws.com/trainings/pdf-sample.pdf";
@Inject
public AutomateWebElements(RpaFactory rpaFactory, Logger logger, SecretsVaultService secretsVault){
this.rpaRunner = rpaFactory
.builder(RpaDriver.UNIVERSAL)
.closeOnCompletion(true)
.build();
this.logger = logger;
this.secretsVault = secretsVault;
}
@Override
public TaskRunnerOutput run(TaskInput taskInput) {
rpaRunner.execute(driver->{
this.automateFileUpload(driver);
});
return taskInput.asResult()
.withColumn("example_bot_task_output", "completed_successfully");
}
private void automateFileUpload(Driver driver){
String loginPage = "https://mail.rediff.com/cgi-bin/login.cgi";
//User needs to create entry of their email credential in secretvault
SecureEntryDTO secureEntry = secretsVault.getEntry("EmailCredentials");
String mailSubject = "Attach PDF";
String mailBody = "This is an RPA message with attached PDF file.";
String filePath = downloadFileOnAgent(s3Path);
logger.debug(" File Path - " + filePath );
RPA.openChrome(loginPage);
RPA.sleep(5 * 1000);
driver.findElement(By.xpath("//input[@id = 'login1']")).sendKeys(secureEntry.getKey());
driver.findElement(By.xpath("//input[@id = 'password']")).sendKeys(secureEntry.getValue());
driver.findElement(By.xpath("/html/body/div/div[1]/div[1]/div[2]/form/div[1]/div[2]/div[2]/div[2]/div/input[2]")).click();
WebElement compose = driver.findElement(By.xpath("//*[@id=\"boxscroll\"]/li[1]/a/b"));
compose.click();
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
WebElement toAddress = driver.findElement(By.xpath("//*[@class=\"rd_inp_to as-input\"]"));
toAddress.click();
toAddress.sendKeys("shubham.shukla2307@rediffmail.com");
WebElement subject = driver.findElement(By.xpath("//*[@id=\"rd_compose_cmp2\"]/ul/li[4]/input"));
subject.sendKeys(mailSubject, Keys.TAB);
//Clicking on Attachment icon
WebElement attach = driver.findElement(By.xpath("//a[@class='attch_fil']"));
attach.click();
RPA.sleep(2000);
//Selecting File To Be Uploaded
RPA.switchTo().window("[CLASS:#32770]");
$("[CLASS:Edit;INSTANCE:1]").sendKeys(filePath);
$("[CLASS:Button;INSTANCE:1]").click();
WebElement emailBodyIframe = driver.findElement(By.xpath("//*[@id=\"cke_1_contents\"]/iframe"));
driver.switchTo().frame(emailBodyIframe);
driver.switchDriver("chrome");
WebElement emailBody = driver.findElement(By.xpath("/html/body"));
emailBody.click();
driver.executeScript("arguments[0].innerHTML = arguments[1]" ,emailBody , mailBody );
driver.switchTo().defaultContent();
WebElement send = driver.findElement(By.xpath("//*[@id=\"rd_compose_cmp2\"]/div[1]/a[1]"));
send.click();
logger.debug("Email Sent");
}
}
The same example that uses the Universal Driver is as follows.
Expand to view the code
<?xml version="1.0" encoding="UTF-8"?>
<config xmlns="http://web-harvest.sourceforge.net/schema/1.0/config" scriptlang="groovy">
<robotics-flow>
<robot name="bb8" driver="universal" close-on-completion="true">
<capability name="SEARCH_ALL_WINDOWS" value="true" />
<script> <![CDATA[
// Copy the file to the RPA machine.
def s3Path = 'https://rpa-tutorial.s3.amazonaws.com/trainings/pdf-sample.pdf'
filePath = downloadFileOnAgent(s3Path)
def loginPage = 'http://mail.google.com'
def username = 'tuk.tuk.rpa@gmail.com'
def password = 'work4WorkFusion!1'
def mailSubject = 'Attach PDF'
def mailBody = 'This is an RPA message with attached PDF file.'
timeouts(20 * 1000)
// Login into the mail system
openIE(loginPage)
$('#identifierId').val(username).pressEnter()
$(byXpath("//*[@name='password']")).val(password)
$('#passwordNext').click()
// Populate new message fields
$(byText('COMPOSE')).click();
$(By.name('to')).val(username).pressTab()
$(by('placeholder', 'Subject')).val(mailSubject).pressTab()
$('.editable').val(mailBody).pressEnter()
// Start attaching file.
$(byXpath("//div[@class='a1 aaA aMZ']")).click()
// Attach file using "upload file" dialog.
switchTo().window('[CLASS:#32770]')
$('[CLASS:Edit;INSTANCE:1]').sendKeys(filePath)
$('[CLASS:Button;INSTANCE:1]').click()
switchTo().window('[CLASS:IEFrame]')
$(byText('Send')).click()
$(withText('Your message has been sent')).shouldBe(VISIBLE)
sleep(3000)
]]></script>
</robot>
</robotics-flow>
<export include-original-data="false">
<single-column name="rpa_local_file_path" value="${filePath}"/>
</export>
</config>