PuppeteerSharp 在asp.net中使用 PuppeteerSharp生命周期管理


2020-12-22 更新,以下代碼有坑不要使用,回過頭來看,發現以前寫的東西好爛呀,哈哈哈哈。。。

博客就放這里給自己留個紀念。

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

 

1.PuppeteerSharp在asp.net中使用的坑:

  1.如果使用nuget下載PuppeteerSharp 則還需要添加PuppeteerSharp.AspNetFramework包依賴。

  2.需要下載chromium 瀏覽器文件 參考https://www.cnblogs.com/cdyy/p/PuppeteerSharp.html 這篇博客。

  3.手動添加依賴包,參考如下:

      a.通過nuget 添加以下包

 

 

 

  左圖是包版本,右圖是需要下載的包。

2.將PuppeteerSharp 生命周期交給autofac管理

  前提:一個asp.net 應用程序只需要啟動一個chromium 進程,當寄宿在IIS中的asp.net應用程序 停止或被回收 時,chromium 進程也需要被關閉掉。

     通過啟動的chromium瀏覽器開啟“Page”頁,每一次的請求打開的page頁(一個或多個),將在請求結束后自動銷毀掉。

 

  這里提供下思路,參考代碼如下: 

  1).創建 IChromiumBrowser,這里封裝了下PuppeteerSharp 的 Browser 對象。

    public interface IChromiumBrowser : IDisposable,IAsyncDisposable
    {  
        Task<Browser> GetBrowserAsync();
    }

       實現

public class ChromiumBrowserAspNet : IChromiumBrowser
    {
        private readonly LaunchOptions _launchOptions;

        public ChromiumBrowserAspNet()
        {
            _launchOptions = new LaunchOptions();
            DetectBrowserFile();
        }

        private Browser _browser;
        private bool _existsBrowserFile;
        private static readonly object Lock = new object();

        public async Task<Browser> GetBrowserAsync()
        {
            if (_browser != null) return _browser;

            await Task.Run(() =>
            {
                lock (Lock)
                {
                    if (_browser == null)
                    {
                        //請提前下載好瀏覽器相關文件
                        //await new BrowserFetcher().DownloadAsync(BrowserFetcher.DefaultRevision);
                        _browser = Puppeteer.LaunchAsync(_launchOptions).Result;
                        //如果瀏覽器進程被其他操作強制關閉,釋放_browser。
                        _browser.Disconnected += (a, b) =>
                        {
                            if (_browser == null) return;
                            Dispose(true);
                        };
                    }
                }
            });
            return _browser;
        }

        private void DetectBrowserFile()
        {
            if (_existsBrowserFile) return;
            string platForm = null;
            if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
            {
                platForm = Platform.MacOS.ToString();
            }

            if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
            {
                platForm = Platform.Linux.ToString();
            }

            if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
            {
                platForm = RuntimeInformation.OSArchitecture == Architecture.X64 ? Platform.Win64.ToString() : Platform.Win32.ToString();
            }

            string folder = Path.Combine(Directory.GetCurrentDirectory(), ".local-chromium");
            string filePath = Path.Combine(folder, $"{platForm}-{BrowserFetcher.DefaultRevision}");
            _existsBrowserFile = new DirectoryInfo(filePath).Exists;
            if (!_existsBrowserFile)
            {
                throw new Exception($"{filePath}");
            }
        }

        protected virtual void Dispose(bool disposing)
        {
            if (disposing)
            {
                _browser?.Dispose();
            }
            _browser = null;
        }

        public void Dispose()
        {
            Dispose(disposing: true);
            GC.SuppressFinalize(this);
        }

        public async ValueTask DisposeAsync()
        {
            await DisposeAsyncCore();

            Dispose(disposing: false);
            GC.SuppressFinalize(this);
        }

        protected virtual async ValueTask DisposeAsyncCore()
        {
            if (_browser != null)
            {
                await _browser.DisposeAsync();
            }

            _browser = null;
        }

    }

   2).通過browser創建page 頁 。名字你自己取,我的叫IPuppeteerSharpContext

    public interface IPuppeteerSharpContext : IDisposable, IAsyncDisposable
    {

        List<IPuppeteerSharpPage> PuppeteerSharpPages { get; }
        Task<List<IPuppeteerSharpPage>> GetPagesAsync(List<PageSetting> pageSettings);
      Task<IPuppeteerSharpPage> GetPageAsync(PageSetting pageSetting);
    }

    實現

    public class PuppeteerSharpContextAspNet : IPuppeteerSharpContext
    {
        private readonly IChromiumBrowser _chromiumBrowser;

        public PuppeteerSharpContextAspNet(IChromiumBrowser chromiumBrowser)
        {
            _chromiumBrowser = chromiumBrowser;
            _puppeteerSharpPages = new List<IPuppeteerSharpPage>();
        }

        private Browser _browser;

        private async Task StarUpPageAsync()
        {
            if (_browser == null)
            {
                _browser = await _chromiumBrowser.GetBrowserAsync();
            }
        }

        private List<IPuppeteerSharpPage> _puppeteerSharpPages;

        public List<IPuppeteerSharpPage> PuppeteerSharpPages => _puppeteerSharpPages;

        public async Task<List<IPuppeteerSharpPage>> GetPagesAsync(List<PageSetting> pageSettings)
        {
            if (pageSettings == null) throw new Exception("pageSettings is null");

            await StarUpPageAsync();

            var list = new List<IPuppeteerSharpPage>();
            pageSettings.ForEach(item =>
            {
                var page = new PuppeteerSharpPage(item, _browser);
                list.Add(page);
                _puppeteerSharpPages.Add(page);
            });
            return list;
        }


        public async Task<IPuppeteerSharpPage> GetPageAsync(PageSetting pageSetting)
        {
            if (pageSetting == null) throw new Exception("pageSetting is null");

            await StarUpPageAsync();

            var page = new PuppeteerSharpPage(pageSetting, _browser);
            _puppeteerSharpPages.Add(page);
            return page;
        }


        protected virtual void Dispose(bool disposing)
        {
            if (disposing)
            {
                _puppeteerSharpPages?.ForEach(item => item.Dispose());
            }
            _puppeteerSharpPages = null;
        }

        public void Dispose()
        {
            Dispose(disposing: true);
            GC.SuppressFinalize(this);
        }

        public async ValueTask DisposeAsync()
        {
            await DisposeAsyncCore();
            Dispose(disposing: false);
            GC.SuppressFinalize(this);
        }

        protected virtual async ValueTask DisposeAsyncCore()
        {
            if (_puppeteerSharpPages != null)
            {
                foreach (var item in _puppeteerSharpPages)
                {
                    await item.DisposeAsync();
                }
            }
            _puppeteerSharpPages = null;
        }
    }

    IPuppeteerSharpPage和PuppeteerSharpPage 根據你自己情況去實現。

  3).將ChromiumBrowser 、“Page”交給autofac管理,參考 https://www.cnblogs.com/bluesummer/p/9041802.html  “IRegisteredObject”

    /// <summary>
    /// Asp.Net IIS宿主環境配置 <see cref="WebAppEnviroment" />.
    /// </summary>
    public class WebAppEnviroment : IRegisteredObject
    {
        public WebAppEnviroment()
        {
            HostingEnvironment.RegisterObject(this);
        }

        private static IChromiumBrowser _chromiumBrowser;

        public void RegisterBrowserModule(ContainerBuilder builder)
        {
            builder.Register(context =>
            {
                IChromiumBrowser browser = new ChromiumBrowserAspNet();
                _chromiumBrowser = browser;
                return browser;
            }).As<IChromiumBrowser>().SingleInstance();
            builder.RegisterType<PuppeteerSharpContextAspNet>().As<IPuppeteerSharpContext>().InstancePerRequest();
        }

        public void Stop(bool immediate)
        {
            if (_chromiumBrowser != null)
            {
                _chromiumBrowser.Dispose();
                _chromiumBrowser = null;
            }
            HostingEnvironment.UnregisterObject(this);
        }
    }

    public static class ContainerBuilderExtsionTes
    {
        public static void RegisterBrowserModule(this ContainerBuilder builder)
        {
            var app = new WebAppEnviroment();
            app.RegisterBrowserModule(builder);
        }
    }

  這里是將ChromiumBrowser創建成了單例,因為只需要存在一個(只需要存在一個browser 瀏覽器),IPuppeteerSharpContext 則是每次請求一個只創建一個實例,然后通過 IPuppeteerSharpContext去創建page頁和釋放page頁。

  大致思路就是這樣,也不知道有沒有講清楚。 這里不提供具體實現代碼。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM