Selenium C#无法点击iframe中embed内PDF下载按钮的问题
点击iframe内嵌embed的PDF查看器下载按钮失败
问题详情
页面中存在一个承载PDF查看器的iframe,内部通过embed元素渲染PDF,尝试点击查看器的下载箭头但无法定位到目标按钮。
页面结构代码:
<div id="__pdfviewer0" data-sap-ui="__pdfviewer0" role="document" aria-label="PDF-Viewer" style="width: 100%; height: 100%;"> <iframe id="__pdfviewer0-iframe" src="blob:https://foo#view=FitH" aria-label="PDF-Viewer: Inhalt" class="sapMPDFViewerContent" cd_frame_id_="fooCodeframe"/> #document (blob:https://foo#view=FitH) <!DOCTYPE html> <html> <head></head> <body style="height: 100%; width: 100%; overflow: hidden; margin:0px; background-color: rgb(82, 86, 89);"> <embed name="fooCode" style="position:absolute; left: 0; top: 0;" width="100%" height="100%" src="about:blank" type="application/pdf" internalid="fooCode"/> </body> </html> </iframe> </div>
尝试的CSS选择器:
[id=viewer] /deep/ [id=toolbar] /deep/ [id=end] > [id=downloads] /deep/ [id='download']
尝试的C#代码:
var frame = Client.Value.WebDriver.SwitchTo().Frame(FindElement(By.Id("__pdfviewer0-iframe"))); frame.FindElement(By.CssSelector("[id=viewer] /deep/ [id=toolbar] /deep/ [id=end] > [id=downloads] /deep/ [id='download']")).Click();
解决方法
1. 处理Shadow DOM(原生PDF查看器)
浏览器原生PDF查看器的控件位于Shadow DOM中,/deep/ 已被废弃,需通过JavaScript访问Shadow Root来定位元素:
// 切换到PDF iframe var pdfIframe = Client.Value.WebDriver.FindElement(By.Id("__pdfviewer0-iframe")); Client.Value.WebDriver.SwitchTo().Frame(pdfIframe); // 显式等待viewer元素加载完成 var wait = new WebDriverWait(Client.Value.WebDriver, TimeSpan.FromSeconds(15)); var viewer = wait.Until(d => d.FindElement(By.Id("viewer"))); // 逐层获取Shadow Root并定位下载按钮 IWebElement viewerShadow = (IWebElement)((IJavaScriptExecutor)Client.Value.WebDriver).ExecuteScript("return arguments[0].shadowRoot", viewer); var toolbar = viewerShadow.FindElement(By.Id("toolbar")); IWebElement toolbarShadow = (IWebElement)((IJavaScriptExecutor)Client.Value.WebDriver).ExecuteScript("return arguments[0].shadowRoot", toolbar); var downloadBtn = toolbarShadow.FindElement(By.CssSelector("#end #downloads #download")); downloadBtn.Click(); // 切回主文档 Client.Value.WebDriver.SwitchTo().DefaultContent();
2. 直接通过URL触发下载(更稳定)
无需定位按钮,直接获取PDF的Blob URL,通过JavaScript创建下载链接:
var pdfIframe = Client.Value.WebDriver.FindElement(By.Id("__pdfviewer0-iframe")); var pdfBlobUrl = pdfIframe.GetAttribute("src"); // 执行JS触发下载 ((IJavaScriptExecutor)Client.Value.WebDriver).ExecuteScript(@" const link = document.createElement('a'); link.href = arguments[0]; link.download = 'downloaded.pdf'; document.body.appendChild(link); link.click(); document.body.removeChild(link); ", pdfBlobUrl);
3. 检查元素定位时机
确保PDF完全加载后再执行定位操作,可通过等待iframe的readyState为complete:
wait.Until(d => ((IJavaScriptExecutor)d).ExecuteScript("return arguments[0].readyState", pdfIframe).ToString() == "complete");
内容的提问来源于stack exchange,提问作者Noob_Number_1
相关产品推荐
相关产品推荐

