在我的角度应用中,我有以下不变的基本条件:
文件。这个HTML文件可能包含带有data:image/jpeg;base64,...
-like源的图像(但没有外部链接)。
我成功地用JSZip等实现了1和2。因此,我们可以假设,现在有一个String
变量htmlFileContent
。在另一个空角选项卡中显示特定条件下的iFrame也不是问题,我设法做到了。为了实现第3点的其余部分,我看到了两种不同的方法:
使用div::
使用htmlFileContent
作为div
元素的innerHTML
,如下所示:
<div [innerHtml]="{{ htmlFileContent }}"></div>
这确实有效,但有一些令人难以置信的副作用,例如,“内部”title
标题也在浏览器中呈现。因此,我可以尝试将htmlFileContent
解析为DOM,并删除不需要的树元素。这也许是一个可行的解决方案,但不知怎么的,我对此并不满意。
此外,HTML还包含一些文件中的锚链接(<a href="#topOfPage">
样式),这些链接也将不再工作,需要进行更正。
使用 iFrame
我非常了解iFrame用法的丑陋和贬义,尽管如此,在我看来,这似乎是解决我的问题的适当方法。所以我会用:
<iframe [src]="fileUrl" class="fullscreenIFrame"></iframe>
这里出现了一个问题:可以设置fileUrl="data:text/html;charset=utf-8,"+ htmlFileContent
。但是,角质会(正确地)抱怨:ERROR Error: NG0904: unsafe value used in a resource URL context (see https://g.co/ng/security#xss)
和任何东西都不会显示。因此,目前我正在使用来自DomSanitizer
的@angular/platform-browser
进行类似的尝试
this.filedata = this.sanitizer.bypassSecurityTrustHtml(htmlFileContent);
this.fileUrl = this.sanitizer.bypassSecurityTrustResourceUrl("data:text/html;charset=utf-8,"+ this.filedata) ;
这在一定程度上是可行的:我在输出中呈现了一个警告SafeValue must use [property]=binding:
,并在第一个src="data:..."
图像出现的地方剪切了“内部”src="data:..."
。
我被困在这里了。当然,我的iFrame只能有一个src
,我不能连接fileUrl
(然后将其缩短为data:text/html;charset=utf-8,
内容)和fileData
,因为其中一个是SafeResourceUrl
,另一个是SafeHtml
对象。
以下是我的问题所在:
https://stackblitz.com/edit/angular-ivy-uzpcsy?file=src/app/app.component.ts
(有趣的是,图像在这里呈现.无论如何,SafeValue
警告仍然存在。)
对于如何处理这一特殊要求,您有什么建议吗?div
-approach还会是更好的吗?任何帮助都是非常感谢的--非常感谢!
发布于 2022-05-24 06:08:40
由于我没有收到或找到另一种可能性,所以我实现它的方式--仅供参考:
import { ActivatedRoute, Router, UrlSegment } from '@angular/router';
import { DomSanitizer, SafeHtml, SafeResourceUrl } from '@angular/platform-browser';
export class MyComponent implements OnInit {
filedata: SafeHtml = 'Loading...';
currentUrl: string = '';
constructor(
private activatedRoute: ActivatedRoute,
private sanitizer: DomSanitizer,
) {}
ngOnInit(): void {
// Use the Angular possibilities to retrieve to complete current URL
this.activatedRoute.url.subscribe(url => {
this.currentUrl = '';
url.forEach(urlElement => {
this.currentUrl += urlElement + '/';
});
this.currentUrl = this.currentUrl.substring(0, this.currentUrl.length - 1);
});
this.loadFileData();
}
loadFileData(): void {
// This is the function where the ZIP file is downloaded and the file
// content is extracted. As it is not part of the question or the
// answer, I will not post it here.
// Let's just assume, the file content is now stored in "response".
this.filedata =
this.sanitizer.bypassSecurityTrustHtml(this.correctFileData(response));
}
// Receives the file content response as first parameter,
// removes the unwanted tags and corrects the anchor links.
private correctFileData(response: string): string {
let el = document.createElement('html');
el.innerHTML = response;
// Remove all "head" tags including their inner elements
// (Of course, the should be only one head tag, but you never know...)
let headElements = el.getElementsByTagName('head');
for (let i = 0; i < headElements.length; i++) {
el.removeChild(headElements[i]);
}
// Correct all anchor links: Prepend the current URL
// So http://my.address.com/#anchor would become
// http://my.address.com/myApp/myRoute/mySubRoute#anchor
// for example
let links = el.getElementsByTagName('a');
for (let i = 0; i < links.length; i++) {
let link = links[i];
if (link.href.indexOf('#') != -1) {
console.log(link.href + ' --> ' + this.currentUrl +
link.href.substring(link.href.indexOf('#')));
link.href = this.currentUrl + link.href.substring(link.href.indexOf('#'));
}
}
return el.outerHTML;
}
在组件的HTML中,我只使用:
<div [innerHTML]="filedata"></div>
可能还有其他更好的解决方案,但这个解决方案对我的用例非常有效。
https://stackoverflow.com/questions/72269891
复制相似问题