Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions common/src/web/downloads/download.html
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ <h1 class="display-6">Downloads</h1>
File 2
</a>
</div>
<div class="form-group tp-align-right mt-3">
<a href="file-with-space 0 & _ ' ~.txt" id="file-3" download>
File 5
</a>
</div>
</div>

</div>
Expand Down
1 change: 1 addition & 0 deletions common/src/web/downloads/file-with-space 0 & _ ' ~.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Hello, filename with space!
16 changes: 16 additions & 0 deletions java/src/org/openqa/selenium/grid/node/local/LocalNode.java
Original file line number Diff line number Diff line change
Expand Up @@ -763,6 +763,8 @@ public HttpResponse downloadFile(HttpRequest req, SessionId id) {
return listDownloadedFiles(downloadsDirectory);
}
if (req.getMethod().equals(HttpMethod.GET)) {
// Left here for backward compatibility.
// Remove this IF in Selenium 4.41, 4.42 or 4.43
return getDownloadedFile(downloadsDirectory, extractFileName(req));
}
if (req.getMethod().equals(HttpMethod.DELETE)) {
Expand Down Expand Up @@ -837,6 +839,14 @@ private HttpResponse getDownloadedFile(HttpRequest req, File downloadsDirectory)
"Please specify file to download in payload as {\"name\":"
+ " \"fileToDownload\"}"));
File file = findDownloadedFile(downloadsDirectory, filename);
String contentType =
requireNonNullElseGet(
(String) incoming.get("format"), () -> MediaType.JSON_UTF_8.toString());

if (MediaType.OCTET_STREAM.toString().equalsIgnoreCase(contentType)) {
return fileAsBinaryResponse(file);
}

String content = Zip.zip(file);
Map<String, Object> data =
Map.of(
Expand All @@ -847,12 +857,18 @@ private HttpResponse getDownloadedFile(HttpRequest req, File downloadsDirectory)
return new HttpResponse().setContent(asJson(result));
}

/** Left here for backward compatibility. Remove this method in Selenium 4.41, 4.42 or 4.43 */
@Deprecated
private HttpResponse getDownloadedFile(File downloadsDirectory, String fileName)
throws IOException {
if (fileName.isEmpty()) {
throw new WebDriverException("Please specify file to download in URL");
}
File file = findDownloadedFile(downloadsDirectory, fileName);
return fileAsBinaryResponse(file);
}

private HttpResponse fileAsBinaryResponse(File file) throws IOException {
BasicFileAttributes attributes = readAttributes(file.toPath(), BasicFileAttributes.class);
return new HttpResponse()
.setHeader("Content-Type", MediaType.OCTET_STREAM.toString())
Expand Down
12 changes: 11 additions & 1 deletion java/src/org/openqa/selenium/remote/DriverCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,17 @@ public interface DriverCommand {
String RESET_COOLDOWN = "resetCooldown";
String GET_DOWNLOADABLE_FILES = "getDownloadableFiles";
String DOWNLOAD_FILE = "downloadFile";
String GET_DOWNLOADED_FILE = "getDownloadedFile";

/**
* This endpoint was introduced in 4.39.0, but not used anymore since 4.40.0. Left here for
* backward compatibility (if someone uses Grid 4.40+, but Client 4.39.0).
*
* <p>Remove it in 4.41, 4.42 or 4.43.
*
* @deprecated use {@link #DOWNLOAD_FILE} instead
*/
@Deprecated String GET_DOWNLOADED_FILE = "getDownloadedFile";

String DELETE_DOWNLOADABLE_FILES = "deleteDownloadableFiles";

static CommandPayload NEW_SESSION(Capabilities capabilities) {
Expand Down
24 changes: 11 additions & 13 deletions java/src/org/openqa/selenium/remote/RemoteWebDriver.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@
package org.openqa.selenium.remote;

import static java.util.Collections.singleton;
import static java.util.Objects.requireNonNull;
import static java.util.concurrent.TimeUnit.SECONDS;
import static java.util.logging.Level.SEVERE;
import static org.openqa.selenium.remote.CapabilityType.PLATFORM_NAME;

import com.google.common.net.MediaType;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
Expand Down Expand Up @@ -69,7 +69,6 @@
import org.openqa.selenium.SearchContext;
import org.openqa.selenium.SessionNotCreatedException;
import org.openqa.selenium.TakesScreenshot;
import org.openqa.selenium.UnsupportedCommandException;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebDriverException;
import org.openqa.selenium.WebElement;
Expand Down Expand Up @@ -732,24 +731,23 @@ public List<DownloadedFile> getDownloadedFiles() {
public void downloadFile(String fileName, Path targetLocation) throws IOException {
requireDownloadsEnabled(capabilities);

try {
Response response = execute(DriverCommand.GET_DOWNLOADED_FILE, Map.of("name", fileName));

Response response =
execute(
DriverCommand.DOWNLOAD_FILE,
Map.of("name", fileName, "format", MediaType.OCTET_STREAM.toString()));
if (response.getValue() instanceof Contents.Supplier) {
// Selenium Grid 4.40.0 or newer
Contents.Supplier content = (Contents.Supplier) response.getValue();
try (InputStream fileContent = content.get()) {
Files.createDirectories(targetLocation);
Files.copy(new BufferedInputStream(fileContent), targetLocation.resolve(fileName));
}
} catch (UnsupportedCommandException e) {
String error = requireNonNull(e.getMessage(), e.toString()).split("\n", 2)[0];
LOG.log(
Level.WARNING,
"You have too old Selenium Grid version, please upgrade it. Caused by: {0}",
error);

Response response = execute(DriverCommand.DOWNLOAD_FILE, Map.of("name", fileName));
} else if (response.getValue() instanceof Map) {
// Selenium Grid 4.39.0 or older
String contents = ((Map<String, String>) response.getValue()).get("contents");
Zip.unzip(contents, targetLocation.toFile());
} else {
throw new UnsupportedOperationException("Unexpected grid response: " + response);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,13 @@
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import org.openqa.selenium.By;
import org.openqa.selenium.Capabilities;
import org.openqa.selenium.HasDownloads;
Expand Down Expand Up @@ -112,36 +116,48 @@ void canListDownloadedFiles() {
driver.get(appServer.whereIs("downloads/download.html"));
driver.findElement(By.id("file-1")).click();
driver.findElement(By.id("file-2")).click();
waitForDownloadedFiles(driver, 2);
driver.findElement(By.id("file-3")).click();
waitForDownloadedFiles(driver, 3);

@SuppressWarnings("deprecation")
List<String> downloadableFiles = ((HasDownloads) driver).getDownloadableFiles();
assertThat(downloadableFiles).contains("file_1.txt", "file_2.jpg");
assertThat(downloadableFiles)
.contains("file_1.txt", "file_2.jpg", "file-with-space 0 & _ ' ~.txt");

List<DownloadedFile> downloadedFiles = ((HasDownloads) driver).getDownloadedFiles();
assertThat(downloadedFiles.stream().map(f -> f.getName()).collect(Collectors.toList()))
.contains("file_1.txt", "file_2.jpg");
.contains("file_1.txt", "file_2.jpg", "file-with-space 0 & _ ' ~.txt");
}

@Test
@ParameterizedTest
@MethodSource("downloadableFiles")
@Ignore(IE)
@Ignore(SAFARI)
void canDownloadFiles() throws IOException {
void canDownloadFiles(By selector, String expectedFileName, String expectedFileContent)
throws IOException {
driver = createWebdriver(capabilities);

driver.get(appServer.whereIs("downloads/download.html"));
driver.findElement(By.id("file-1")).click();
driver.findElement(selector).click();
waitForDownloadedFiles(driver, 1);

DownloadedFile file = ((HasDownloads) driver).getDownloadedFiles().get(0);
assertThat(file.getName()).isEqualTo(expectedFileName);

Path targetLocation = Files.createTempDirectory("download");
((HasDownloads) driver).downloadFile(file.getName(), targetLocation);

File localFile = targetLocation.resolve(file.getName()).toFile();
assertThat(localFile).hasName(file.getName());
File localFile = targetLocation.resolve(expectedFileName).toFile();
assertThat(localFile).hasName(expectedFileName);
assertThat(localFile).hasSize(file.getSize());
assertThat(localFile).content().isEqualToIgnoringNewLines("Hello, World!");
assertThat(localFile).content().isEqualToIgnoringNewLines(expectedFileContent);
}

static Stream<Arguments> downloadableFiles() {
return Stream.of(
Arguments.of(By.id("file-1"), "file_1.txt", "Hello, World!"),
Arguments.of(
By.id("file-3"), "file-with-space 0 & _ ' ~.txt", "Hello, filename with space!"));
}

@Test
Expand Down