Как дождаться загрузки файла?

Пишу скирпт, который авторизуется на сайте и после этого загружает с него (скачивает) файл.
Загрузка файла с сервера на мой компьютер — клик по кнопке на странице.
Всё работает, но после полной загрузки файла мне нужно закрыть driver (закрыть браузер).
Как определить, что файл уже загружен?

Привет,

Как вариант, смотреть на скачиваемый файл и ждать пока его размер не будет изменяться)

При скачивании браузер создает временный файл. Вот по нему и можно трекать

Юзал в свое время этот воркераунд для Watir: Ruby / Watir-Webdriver download file

У нас сейчас сделано так:

  1. перед нажатием кнопки “скачать” в Download-дире берется список файлов
  2. после нажатия кнопки “скачать” сначала ожидается появление файла, которого до этого не было
  3. после этого ожидается скачивание файла
    1. если появившийся файл временный, то ожидается, когда он исчезнет и появится постоянный -> скачивание завершено
    2. если появившийся файл сразу не временный, то считается что скачивание завершено

В общих чертах так

1 лайк

Всем большое спасибо. Мысли по поводу костыльной проверки наличия и размера файла были. Я надеялся, что ожидание можно реализовать силами самого Selenium. Увы. На самом деле мне подошло банальное ожидание в 5 секунд после клика на ссылку (файл в реальности грузится менее секунды). Хотел на будущее иметь правильное решение.

Вместо размера лучше проверять его хэш сумму (sha-1 как best practice), чтобы быть на 100% уверенными, что файл скачался и не битый.

1 лайк

Это если мы знаем конечный размер файла.
У меня это была выгрузка CSV из Яндекс.Метрики. Каждый раз размер разный.

Используйте прокси.

http://selenium2.ru/news/106-selenium-i-browsermobproxy-vmeste-veselee.html

1 лайк

Не подскажете как в авто тесте на Java поставить ожидание 5 секунд чтобы успевал загрузится файл.

@After
//stop(5сек)
driver.quit();
}

PS. Заранее спасибо за помощь

TimeUnit.SECONDS.sleep(5);

Но… это дикий антипаттерн. Хардкоду - бой.

1 лайк

Спасибо огромное всё работает :blush:

Согласен но не знаю как сделать лучше, нужно дождаться пока фаил загрузится а потом закрыть браузер. Из данной темы я понял что команды ожидать окончания загрузки нет.

Лично я эту проблему решил следующим образом.
Пример, конечно же, с C#, а не Java, но в принципе из основных отличий - что это просто в джаве будет не метод расширения.

Создал такой метод:

public static FileInfo DownloadFile(this IWebDriver driver, Action action, TimeSpan timespan)
        {
            FileInfo newFile = null;
            lock (Locker)
            {
                var directoryFiles = DriverManager.DowndloadFolder.EnumerateFiles().ToList();
                action.Invoke();

                driver.Wait(timespan)
                    .Until(() => DriverManager.DowndloadFolder.EnumerateFiles().Count() != directoryFiles.Count);
                do
                {
                    foreach (var enumerateFile in DriverManager.DowndloadFolder.EnumerateFiles())
                        if (directoryFiles.All(_ => _.Name != enumerateFile.Name))
                            newFile = enumerateFile;
                } while (newFile != null && (newFile.Name.Contains(".tmp") || newFile.Name.Contains("crdownload")));
            }

            if (newFile == null)
                throw new AutoTestErrorException(
                    "Не нашли новый файл в папке загрузок.");
            return newFile;
        }

И использую его с любым действием.
Например - если файл качается по кнопке, то передаём что-то типа этого:

var downloadedFile = DriverManager.Driver.DownloadFile(() => downloadBtn.Click, TimeSpan.FromSeconds(3))

Если просто по ссылке качаем (без интерфейса), то аналогичным образом - только метод, отправляющий запрос на скачивание.

1 лайк

Сама по себе автоматизация скачивания файла весьма спорное решение

@TesterTesterman

Используйте Selenide. Там есть готовый метод для скачивания файла:

File report = $("a#report").download();

Более того, вам даже driver.quit() не придётся вызывать.

1 лайк

Время прошло, но все еще актуально ))
Как сделать, чтобы не создавались промежуточные папки в пути куда скачивается файл?

Например:
Configuration.downloadsFolder = “D:\Reports\”;

При скачивании отчета, у меня получается путь

  1. D:\Reports\1617786414286_28004_1\Report.txt - если напрямую нажимать на ссылку скачивания

  2. D:\Reports\5d4af502-96af-4eb4-b3b6-b6908153d48a\Report.txt - если качать файл через download метод

почему оно создает еще промежуточные эти папки и как от них избавитсья?

Популярный вопрос :slight_smile:

Эти промежуточные папки специально создаются, чтобы гарантировать, что в той же папке для скачивания уже не окажется файла с таким же именем - скажем, оставшегося от предыдущего теста.

Правильный ответ такой: вам не нужно удалять эти папки. Они вам не мешают.
Скорее всего вы просто пытаетесь найти скачанный файл в папке D:\Reports, и вот этого как раз не нужно делать. Метод $.download() уже возвращает объект File - вот это и есть скачанный файл. Его больше не надо нигде искать.

когда ты позаботился заранее о пользователях, а они не ценят :rofl::rofl:

1 лайк

Хех, точно!