I have an HTML a download that doesn't open the save as dialog box

Hi

  1. Is this normal? It turns out that running the same code with Katalon Studio opens the save as dialog box.
  2. Is it so fast that you can’t see it in the video? I doubt it because a delay was set before pressing Enter to check it, and nothing happened.
  3. In our test case, we want to save xxx.pdf (this PDF is fixed and on our server) as [specific path]\General_access_conditions.pdf. Using java.awt.robot works for us in KS. It doesn’t work in TestOps, so I guess that’s why the dialog box doesn’t open?
  4. In the video, you can see that xxx.pdf is downloaded. How can we get that path? I suppose it’s something like /work/test-project/NNNN/¿¿?? With KS, we know it would be C:\Users[execution user]\Downloads

This is a test case for platform registration. Then, we need to verify that the file has been downloaded to enable an “I agree” check.

Thanks

1 Like

did you upload the video attachment?

To handle file downloads in Katalon Studio/TestOps without relying on the “Save As” dialog, along with verifying the downloaded file:

1. Configure Browser to Auto-Download Files

Bypass the dialog by setting browser preferences to auto-download files to a specific directory.

For Chrome:

import org.openqa.selenium.chrome.ChromeOptions
import com.kms.katalon.core.webui.driver.DriverFactory

// Set download directory (use TestOps-safe path)
String downloadDir = "${RunConfiguration.getProjectDir()}/downloads"
new File(downloadDir).mkdirs() // Create folder if missing

ChromeOptions options = new ChromeOptions()
Map<String, Object> prefs = new HashMap<>()
prefs.put("download.default_directory", downloadDir)
prefs.put("download.prompt_for_download", false)
prefs.put("download.directory_upgrade", true)
prefs.put("plugins.always_open_pdf_externally", true) // For PDFs
options.setExperimentalOption("prefs", prefs)

// Apply options
WebUI.openBrowser('', DriverFactory.CHROME_DRIVER_ID, options)

2. Verify File Download

Check if the file exists in the specified directory after triggering the download.

import java.nio.file.Paths

String fileName = "General_access_conditions.pdf"
String expectedFilePath = Paths.get(downloadDir, fileName).toString()

// Wait for download (adjust timeout as needed)
int maxWait = 30 // seconds
int interval = 1
int elapsed = 0

while (elapsed < maxWait) {
    if (new File(expectedFilePath).exists()) {
        KeywordUtil.logInfo("File found: ${expectedFilePath}")
        break
    }
    WebUI.delay(interval)
    elapsed += interval
}

// Assert file exists
assert new File(expectedFilePath).exists() : "File not downloaded: ${fileName}"

// Verify "I Agree" checkbox (example)
WebUI.check(findTestObject('Checkbox_I_Agree'))

3. Handle Downloads in TestOps

File Paths in TestOps:

  • TestOps uses a temporary workspace for each execution. Paths are relative to the project root.
  • Use ${RunConfiguration.getProjectDir()} to get the absolute path.

Modify TestOps Configuration:

  1. Upload Test Data: Place any required files in Data Files (for reference comparisons).
  2. Clean Downloads Between Runs: Add a teardown script to delete temporary files:
new File(downloadDir).deleteDir() // Deletes the "downloads" folder

4. Disable Native Dialogs (Headless Execution)

For TestOps/headless environments, use these capabilities:

options.addArguments("--headless=new")
options.addArguments("--disable-gpu")
options.addArguments("--no-sandbox")

5. Alternative: Use Katalon’s Download Manager

If you need to track download progress, use the Download Manager plugin:

  1. Install from Katalon Store: Download Manager
  2. Sample Usage:
import com.kazurayam.webdriverfactory.DownloadManager

DownloadManager dm = new DownloadManager(downloadDir)
dm.enable() // Starts monitoring
// ... trigger download ...
List<File> downloaded = dm.getDownloadedFiles()

Key Notes

  • Avoid Hard-Coded Paths: Use ${RunConfiguration.getProjectDir()} instead of C:\Users....
  • File Cleanup: Always delete downloaded files post-execution to avoid cluttering TestOps workspaces.
  • PDF Handling: Some browsers require plugins to auto-download PDFs (hence plugins.always_open_pdf_externally).

Troubleshooting

  • Permission Issues: Ensure TestOps agent has write access to the download directory.
  • Dynamic Filenames: Use wildcards or timestamp-based naming:
String fileName = new File(downloadDir).list().find { it.endsWith('.pdf') }

This approach ensures consistent behavior across Katalon Studio and TestOps while eliminating dependency on GUI dialogs.

Hi
Okay. Thanks, I’ll try what you told me.

Sorry, I wasn’t clear about the video that Testops generates. No, I didn’t upload it.
I’m attaching a screenshot from the video showing Chrome downloading the xxx.pdf and, as I said, without giving me the option to save it to a specific location.

Let us know on issue resolution

Hi dineshh
Thanks. You’ve given me some good ideas. What I want is for it to let me download wherever I want and with the name I want.
The code I’ve added is:

ChromeOptions options = new ChromeOptions()
HashMap<String, Object> chromePrefs = new HashMap<String, Object>();
chromePrefs.put('download.prompt_for_download', true);
chromePrefs.put('plugins.always_open_pdf_externally', true);
chromePrefs.put("download.default_directory", downloadDir)
chromePrefs.put("download.directory_upgrade", true)
options.setExperimentalOption('prefs', chromePrefs);
WebDriver driver = new ChromeDriver(options)
DriverFactory.changeWebDriver(driver)
WebUI.navigateToUrl(URL_PORTAL)

But I have a problem: it doesn’t download anything; every download fails. What I see in debugging is that the file is downloaded as tmp while the save screen is open, but when I save it, the file disappears.
image

Any ideas?

1 Like

To resolve the file download issue in Katalon where the PDF temporarily appears but fails to save properly, follow these steps:

1. Correct ChromeOptions Configuration

Ensure auto-download without the “Save As” dialog by setting download.prompt_for_download to false and specifying an absolute path:

import com.kms.katalon.core.webui.driver.DriverFactory
import org.openqa.selenium.chrome.ChromeOptions
import org.openqa.selenium.WebDriver

String downloadDir = "${RunConfiguration.getProjectDir()}/downloads".replace("/", File.separator) // Use OS-specific separators
new File(downloadDir).mkdirs() // Create directory if missing

ChromeOptions options = new ChromeOptions()
HashMap<String, Object> chromePrefs = new HashMap<>()
chromePrefs.put('download.prompt_for_download', false) // Disable dialog
chromePrefs.put('plugins.always_open_pdf_externally', true) // Force PDF download
chromePrefs.put('download.default_directory', downloadDir)
chromePrefs.put('download.directory_upgrade', true) // Overwrite existing files
options.setExperimentalOption('prefs', chromePrefs)

// Add arguments for stability (especially in headless/TestOps)
options.addArguments('--disable-gpu', '--no-sandbox', '--remote-allow-origins=*')

WebDriver driver = new ChromeDriver(options)
DriverFactory.changeWebDriver(driver)

2. Verify File Download with Dynamic Waits

After triggering the download, check for the file with a dynamic wait:

import java.nio.file.Files
import java.nio.file.Paths

String expectedFileName = "General_access_conditions.pdf"
String expectedFilePath = Paths.get(downloadDir, expectedFileName).toString()

int maxWait = 30 // Max wait in seconds
int interval = 1 // Check every 1 second
boolean fileFound = false

for (int elapsed = 0; elapsed < maxWait; elapsed += interval) {
    File downloadedFile = new File(expectedFilePath)
    if (downloadedFile.exists()) {
        fileFound = true
        break
    }
    WebUI.delay(interval)
}

assert fileFound : "File not found at ${expectedFilePath}"

3. Handle Temp Files and Partial Downloads

If files are saved as .tmp and deleted:

  • Add a post-download delay to allow Chrome to complete the download:
// After triggering download
WebUI.delay(5) // Adjust based on file size
  • Check for .tmp files and rename them:
// After triggering download
File tmpFile = new File(Paths.get(downloadDir, "Unconfirmed_*.tmp").toString())
if (tmpFile.exists()) {
    tmpFile.renameTo(new File(expectedFilePath))
}

4. Configure TestOps for File Access

  • Specify Absolute Paths: Use ${RunConfiguration.getProjectDir()} to avoid path ambiguity.
  • Pre-Create Directories: Add a setup script to create downloads folder:
new File("${RunConfiguration.getProjectDir()}/downloads").mkdirs()
  • Clean Up Files post-execution (in teardown script):
new File("${RunConfiguration.getProjectDir()}/downloads").deleteDir()

5. Handle Filename Conflicts

If the server appends timestamps to filenames (e.g., General_access_conditions(1).pdf):

// Find the latest PDF in the download directory
File[] files = new File(downloadDir).listFiles({ file -> file.getName().endsWith('.pdf') } as FileFilter)
files.sort({ a, b -> Long.compare(b.lastModified(), a.lastModified()) }) // Sort by latest
String actualFilePath = files[0].getAbsolutePath()

// Rename to the desired filename
Files.move(Paths.get(actualFilePath), Paths.get(expectedFilePath))

6. Troubleshooting Tips

  • Enable Chrome Logging:
options.setCapability("goog:loggingPrefs", [performance: 'ALL', browser: 'ALL'])

Check logs via DriverFactory.getWebDriver().manage().logs().get('browser').

  • Run in Non-Headless Mode (for local debugging):
options.addArguments('--headless=new') // Remove this line
  • Verify Permissions: Ensure TestOps agent/user has write access to downloadDir.

By configuring Chrome to auto-download without dialogs, dynamically verifying file existence, and handling temp files, you can reliably save the PDF to your desired location with the correct name.