Azure虚拟机部署时PuppeteerSharp DownloadAsync下载Chrome失败求助
问题:Azure虚拟机IIS环境下PuppeteerSharp下载Chrome失败
环境信息
- 基于C#开发,运行在.NET 4.8.1环境,搭配AngularJS(该部分与问题无关)
- 本地Windows 11的localhost/IIS Express环境下,PuppeteerSharp生成PDF功能正常
- 部署环境:Azure虚拟机(64位Windows Server 2019,8GB内存)+ IIS
问题现象
部署到Azure虚拟机后,因Chrome下载失败导致PDF生成流程中断,无法从指定URL获取Chrome安装包。
已尝试操作
- 将Chrome下载路径从TEMP文件夹切换到
inetpub目录,已配置对应权限 - 可通过
curl命令从目标URL下载对应.zip文件 - 可直接通过Chrome浏览器下载该文件
错误信息
Failed to download Chrome for Win64 from https://storage.googleapis.com/chrome-for-testing-public/127.0.6533.88/win64/chrome-win64.zip
调用栈
at PuppeteerSharp.BrowserFetcher.<DownloadAsync>d__39.MoveNext() at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at PuppeteerSharp.BrowserFetcher.<DownloadAsync>d__32.MoveNext() at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at PuppeteerSharp.BrowserFetcher.<DownloadAsync>d__28.MoveNext() at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at App.Application._Core.Chromium.<DownloadChromium>d__13.MoveNext() at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at App.Controllers.API.DataApiController.<GeneratePdf>d__1.MoveNext()
相关代码
数据API控制器端点(C#)
[HttpPost] [Route("some-route")] public async Task<IHttpActionResult> GeneratePdf(RequestDto request) { var chromium = new Chromium(); await chromium.DownloadChromium(); Stream stream = await chromium.CreateStreamAsync(request.Html); MemoryStream ms = new MemoryStream(); stream.CopyTo(ms); var result = new HttpResponseMessage() { Content = new ByteArrayContent(ms.ToArray()), StatusCode = HttpStatusCode.OK }; result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream"); result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment") { FileName = $"{request.pdfName}.pdf" }; return ResponseMessage(result); }
Chromium封装类代码(C#)
/// <summary> /// 基于PuppeteerSharp封装的HTML转PDF工具类 /// </summary> public Chromium() { _Logger = LogManager.GetCurrentClassLogger(); var directory = AppDomain.CurrentDomain.BaseDirectory; var driveDownloads = Path.Combine(directory, "chromium"); _InstallDirectory = driveDownloads; _Logger.Info($"chromium类安装目录: [{_InstallDirectory}]"); } /// <summary> /// 将Chromium下载到指定安装目录 /// </summary> /// <returns></returns> public async Task<bool> DownloadChromium() { SetupChromiumDownloadDirectory(_InstallDirectory); _BrowserFetcher = new BrowserFetcher(new BrowserFetcherOptions() { Path = _InstallDirectory }); _Logger.Info($"浏览器缓存下载目录: [{_BrowserFetcher.CacheDir}]"); // 错误发生在此处 _InstalledBrowser = await _BrowserFetcher.DownloadAsync(); return true; } /// <summary> /// 配置Chromium自定义下载目录,避免默认目录路径过长导致异常 /// </summary> /// <param name="directory"></param> /// <returns></returns> private bool SetupChromiumDownloadDirectory(string directory) { _Logger.Debug($"配置chromium目录: [{directory}]"); bool setup = false; bool exists = Directory.Exists(directory); var directoryInfo = new DirectoryInfo(directory); if (!exists) { _Logger.Debug($"目录不存在,创建目录"); directoryInfo.Create(); } var rule = new FileSystemAccessRule("Everyone", FileSystemRights.FullControl, InheritanceFlags.None, PropagationFlags.NoPropagateInherit, AccessControlType.Allow); var security = directoryInfo.GetAccessControl(AccessControlSections.Access); security.ModifyAccessRule(AccessControlModification.Set, rule, out setup); _Logger.Debug($"为目录[{directory}]设置ModifyAccessControl为SET,结果: [{setup}]"); if (!setup) return false; rule = new FileSystemAccessRule("Everyone", FileSystemRights.FullControl, InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit, PropagationFlags.InheritOnly, AccessControlType.Allow); security.ModifyAccessRule(AccessControlModification.Add, rule, out setup); _Logger.Debug($"为目录[{directory}]设置ModifyAccessControl为ADD,结果: [{setup}]"); if (!setup) return false; directoryInfo.SetAccessControl(security); return setup; }
日志信息
2024-09-20 14:30:53.8350 INFO chromium class install directory: [C:\inetpub\wwwroot\chromium] 2024-09-20 14:30:53.8506 DEBUG Settting up chromium directory: [C:\inetpub\wwwroot\chromium] 2024-09-20 14:30:53.8506 DEBUG Setting ModifyAccessControl to SET for directory: [C:\inetpub\wwwroot\chromium] result: [True] 2024-09-20 14:30:53.8506 DEBUG Setting ModifyAccessControl to ADD for directory: [C:\inetpub\wwwroot\chromium] result: [True] 2024-09-20 14:30:53.8506 INFO browser cache download directory: [C:\inetpub\wwwroot\chromium]
内容的提问来源于stack exchange,提问作者B-M
相关产品推荐
相关产品推荐

