Открывать файлы, загруженные из CEFSharp, в приложении просмотра ОС по умолчанию

Я создал приложение Winforms, используя .NET 4.7.2 и CEFSharp 84.4.10.

У меня загружен веб-сайт со ссылками на различные файлы PDF, TXT, DOCX и т. д. HTML для ссылок выглядит следующим образом:

<a href="relative_url/filename.ext" target="_blank">icon_here</a>

Поэтому, когда я, например, нажимаю ссылку на docx, CEFSharp открывает пустое окно поверх моего приложения, а затем открывает диалоговое окно сохранения файла. Когда вы нажимаете «Сохранить» в диалоговом окне файла, оно закрывается, но пустое окно остается открытым.

введите здесь описание изображения

Я хочу сделать следующее:

  1. Не открывайте пустое окно.

  2. Определить загружаемый тип/мим файла (мое приложение загружает только мой сайт), и если они имеют формат PDF, TXT или DOCX, то автоматически загружаются во временную папку, не отображая диалоговое окно сохранения, и открываются в средстве просмотра ОС по умолчанию.

  3. Если нет ни одного из вышеперечисленных типов, покажите диалоговое окно «Сохранить файл» и позвольте пользователю загрузить его туда, куда он хочет.

Я могу отдельно разобраться, как открыть файл в средстве просмотра ОС по умолчанию, здесь я хочу сосредоточиться на автоматической загрузке определенных типов файлов.

Я часами искал примеры того, как это сделать, и пришел с пустыми руками.

Я думал, что смогу определить тип файла в DownloadHandler.OnBeforeDownload, а затем, основываясь на следующем сообщении, просто установите для showDialogue значение false в обратном вызове, а затем в DownloadHandler.OnDownloadUpdated определите downloadItem.IsComplete, а затем запустите файл, если это правильный тип.

Принудительно загрузить CEFSharp без отображения диалогового окна

Однако, когда я попробовал это, я столкнулся со следующими проблемами:

  1. Пустое окно по-прежнему открывается и остается открытым.

  2. Я обнаружил, что если я устанавливаю точку останова в DownloadHandler.OnDownloadUpdated, я вижу, что ReceivedBytes переходят от нуля к TotalBytes, а InProgress является истинным, а затем, когда я продолжаю нажимать F5, чтобы продолжить, ReceivedBytes возвращается к нулю, а InProgress имеет значение false , но IsComplete и IsCanceled все время остаются ложными. Я ожидал, что после завершения загрузки IsComplete будет правдой.

Мне нравится работать с CEFShap, и любые указания или примеры, которые могут быть предоставлены, будут высоко оценены.

Спасибо за ваше время.

ОБНОВЛЕНИЕ 1:

Код, который я пробовал, выглядит следующим образом:

ПРИМЕЧАНИЕ. Я обнаружил, что после назначения пути к обратному вызову. Продолжить в OBeforeDownload исправлено, что IsComplete не устанавливается на истинную проблему. Однако проблема глухого оконного проема остается.

В хостинге winform CEFSharp я инициализировал элемент управления следующим образом:

browser = new ChromiumWebBrowser("https://localhost:44393/Default.aspx");
var downloadHandler = new DownloadHandler();
browser.DownloadHandler = downloadHandler;

В DownloadHandler.cs:

public class DownloadHandler : IDownloadHandler
{
    public event EventHandler<DownloadItem> OnBeforeDownloadFired;
    public event EventHandler<DownloadItem> OnDownloadUpdatedFired;

    public void OnBeforeDownload(IWebBrowser chromiumWebBrowser, IBrowser browser, DownloadItem downloadItem, IBeforeDownloadCallback callback)
    {
        OnBeforeDownloadFired?.Invoke(this, downloadItem);

        if (!callback.IsDisposed)
        {
            using (callback)
            {
                //TODO: Detect file Type/Mime and auto download or show Save File dialogue as needed here
                callback.Continue(Path.Combine(@"C:\Temp", downloadItem.SuggestedFileName), showDialog: false); // set to false so we don't show 
            }
        }
    }

    public void OnDownloadUpdated(IWebBrowser chromiumWebBrowser, IBrowser browser, DownloadItem downloadItem, IDownloadItemCallback callback)
    {
        OnDownloadUpdatedFired?.Invoke(this, downloadItem);
        if (downloadItem.IsComplete)
        {
            //TODO: Detect File Type/Mime and automatically open in default OS viewer
        }
    }
}

person Scotty Laughton    schedule 09.09.2020    source источник
comment
Что вы пробовали? Пожалуйста, отредактируйте свой вопрос и предоставьте код, который у вас есть до сих пор.   -  person amaitland    schedule 09.09.2020
comment
@amaitland спасибо за ответ. Я сделаю один лучше, я создам демонстрационный проект и обновлю пост с ним. Следите за обновлениями ;-)   -  person Scotty Laughton    schedule 09.09.2020
comment
Большой. Пожалуйста, без zip-файлов, я просматриваю 99% кода на планшете Android. GitHub, Bitbucket и т. д. предпочтительнее.   -  person amaitland    schedule 09.09.2020
comment
@amaitland, ах .... хорошо, я только что создал полностью рабочий проект VS2019 с веб-сайтом для обслуживания файла docx, где вы могли бы воспроизвести проблему. Неважно, вместо этого я просто добавлю примеры кода в пост. Я вижу вас в некоторых постах на magpcss.org. Я пытался зарегистрироваться, но я не получаю письмо с подтверждением, не в спаме, и в их FAQ они говорят, что если это произойдет, ...попробуйте связаться с администратором..., но нет ссылки для связи с администратором.   -  person Scotty Laughton    schedule 09.09.2020
comment
@amaitland хорошо, я добавил пример кода   -  person Scotty Laughton    schedule 09.09.2020
comment
Вы можете загрузить свое решение на Github (бесплатно для проектов с открытым исходным кодом). Ваша ссылка указывает цель _blank, поэтому она открывает всплывающее окно по запросу. Если вам вообще не нужно иметь всплывающее окно, то проще всего изменить HTML-код, иначе вам нужно закрыть всплывающее окно, см. magpcss.org/ceforum/viewtopic.php?f=6&t=16516#p40729   -  person amaitland    schedule 09.09.2020
comment
@amaitland хорошо, так что это _BLANK вызывает всплывающее окно. Сайт должен работать как в обычных настольных браузерах, так и в CEFSharp. Жаль, что нельзя сказать, не показывать всплывающее окно. Интересно, смогу ли я преобразовать всплывающее окно в новую вкладку, я думаю, это будет меньше сталкиваться с пользователями.   -  person Scotty Laughton    schedule 09.09.2020
comment
Вкладки более сложны, так как вам придется реализовать свой собственный элемент управления вкладками, встроенной поддержки нет. Вы можете отменить всплывающее окно, тогда вам придется вручную загрузить файл. Что достаточно легко. Это действительно зависит от вашего варианта использования. Если вы не знакомы с целевым атрибутом, лучше прочитать developer.mozilla .org/en-US/docs/Web/HTML/Element/a   -  person amaitland    schedule 09.09.2020
comment
@amaitland хорошо, круто. Я использую EasyTabs. Возможно, лучший вариант — отменить всплывающее окно и загрузить файл самостоятельно. Так является ли правильным способом отменить всплывающее окно, просто установив для параметра newBrowser OnBeforePopup значение null, а затем вызвать оттуда мой собственный асинхронный код, чтобы загрузить файл и открыть его в средстве просмотра по умолчанию?   -  person Scotty Laughton    schedule 09.09.2020
comment
Если ваш сайт не нуждается в аутентификации, это, вероятно, нормально. Лучше всего создать новую задачу для выполнения загрузки или вы можете вызвать cefsharp. github.io/api/84.4.x/html/, чтобы запустить загрузку и использовать ту же реализацию IDownloadHandler, что и обычно.   -  person amaitland    schedule 09.09.2020
comment
@amaitland спасибо, что нашли время ответить на мои вопросы. У меня есть еще один. Когда я создаю класс, наследуемый от ILifeSpanHandler, я должен реализовать DoClose, OnAfterCreated, OnBeforeClose и OnBeforePopup. Меня интересует только последний. Я просто оставляю все остальные пустыми, или мне нужно делать какую-то базовую реализацию?   -  person Scotty Laughton    schedule 09.09.2020
comment
Если метод возвращает void, ничего не делайте, если он возвращает bool, то по умолчанию используется значение return false. Это интерфейс, поэтому базовой реализации нет.   -  person amaitland    schedule 09.09.2020