You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Umbraco中替换YouTube嵌入链接为缩略图并覆写文件的技术求助

解决Umbraco中YouTube嵌入替换为缩略图的问题

首先,咱们先理清几个关键的认知误区,再一步步实现你的需求:

1. Angular不能直接调用C#文件/方法

你当前代码里的ng-controller="WebApplication1\WebApplication1\ManipulateRenderedHtml.cs"和ng-click里直接用File.ReadAllText是完全错误的——Angular的控制器是前端JS文件,不能直接指向后端C#文件,也没法直接调用后端的文件读取方法。咱们得把前后端的交互逻辑理顺:

  • 后端负责读取/修改HTML内容(或者直接在Razor视图里处理)
  • 前端通过HTTP请求调用后端接口,或者直接渲染后端处理好的内容

2. 正确实现YouTube iframe替换为缩略图的逻辑

核心思路是:提取YouTube视频ID,生成对应缩略图,用图片替代iframe;点击图片时再动态加载iframe(这样初始加载不会触发YouTube的Cookie)。

方法一:在Razor视图中直接处理(最简单,推荐)

既然你用的是Umbraco的Razor视图,咱们可以直接在视图里写一个辅助方法来替换iframe,不需要额外的后端接口:

@inherits Umbraco.Web.Mvc.UmbracoViewPage<ContentModels.Blog> 
@using Umbraco.Web; 
@{ 
    Layout = "master.cshtml"; 

    // 定义替换YouTube iframe的辅助方法
    string ReplaceYoutubeIframes(string htmlContent)
    {
        // 匹配YouTube embed链接的正则表达式
        var youtubeRegex = new System.Text.RegularExpressions.Regex(@"iframe.*src=""https://www.youtube.com/embed/([a-zA-Z0-9_-]+)""");
        
        return youtubeRegex.Replace(htmlContent, match => {
            var videoId = match.Groups[1].Value;
            // 生成带点击加载逻辑的缩略图HTML
            return $@"<div class=""youtube-thumbnail-container"" data-video-id=""{videoId}"">
                        <img src=""https://img.youtube.com/vi/{videoId}/hqdefault.jpg"" alt=""YouTube视频缩略图"" class=""youtube-thumbnail"" />
                        <span class=""youtube-play-btn"">▶</span>
                      </div>";
        });
    }

    // 这里可以替换成你从Umbraco内容字段读取的HTML,比如Model.BodyContent
    var originalHtml = @"<iframe id=""test"" width=""560"" height=""315"" src=""https://www.youtube.com/embed/5tVGei24TdQ"" frameborder=""0"" allow=""accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture"" allowfullscreen></iframe>";
    var modifiedHtml = ReplaceYoutubeIframes(originalHtml);
} 

@Html.Partial("~/Views/Partials/SectionHeader.cshtml") 
<section class="section"> 
 <div class="container">
    <!-- 渲染处理后的内容,用Html.Raw避免HTML转义 -->
    @Html.Raw(modifiedHtml)

    <!-- 添加点击加载iframe的JS逻辑 -->
    <script>
        document.querySelectorAll('.youtube-thumbnail-container').forEach(container => {
            container.addEventListener('click', () => {
                const videoId = container.dataset.videoId;
                // 替换容器内容为iframe
                container.innerHTML = `<iframe width="560" height="315" src="https://www.youtube.com/embed/${videoId}" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>`;
            });
        });
    </script>

    <!-- 可选:给缩略图加一点样式,让它看起来像可点击的播放器 -->
    <style>
        .youtube-thumbnail-container {
            position: relative;
            display: inline-block;
            cursor: pointer;
        }
        .youtube-play-btn {
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            font-size: 48px;
            color: white;
            text-shadow: 0 0 10px rgba(0,0,0,0.8);
        }
    </style>
 </div> 
</section>

方法二:用后端API处理(适合动态修改视图文件,不推荐生产环境)

如果你确实需要读取并覆写原视图文件(注意:生产环境不建议这么做,视图是源码文件,修改后会导致应用重启),可以创建一个Umbraco SurfaceController:

using System.IO;
using System.Text.RegularExpressions;
using System.Web.Mvc;
using Umbraco.Web.Mvc;

namespace WebApplication1.Controllers
{
    public class YoutubeEmbedController : SurfaceController
    {
        [HttpPost]
        public ActionResult UpdateEmbeds()
        {
            var viewFilePath = Server.MapPath("~/Views/Blog.cshtml");
            var originalViewContent = File.ReadAllText(viewFilePath);

            // 执行替换逻辑
            var youtubeRegex = new Regex(@"iframe.*src=""https://www.youtube.com/embed/([a-zA-Z0-9_-]+)""");
            var modifiedViewContent = youtubeRegex.Replace(originalViewContent, match => {
                var videoId = match.Groups[1].Value;
                return $@"<div class=""youtube-thumbnail-container"" data-video-id=""{videoId}"">
                            <img src=""https://img.youtube.com/vi/{videoId}/hqdefault.jpg"" alt=""YouTube视频缩略图"" class=""youtube-thumbnail"" />
                            <span class=""youtube-play-btn"">▶</span>
                          </div>";
            });

            // 覆写原视图文件
            File.WriteAllText(viewFilePath, modifiedViewContent);

            return Json(new { Success = true, ModifiedContent = modifiedViewContent });
        }
    }
}

然后前端用Angular调用这个接口:

@inherits Umbraco.Web.Mvc.UmbracoViewPage<ContentModels.Blog> 
@using Umbraco.Web; 
@{ Layout = "master.cshtml"; } 
@Html.Partial("~/Views/Partials/SectionHeader.cshtml") 
<section class="section"> 
 <div class="container" ng-controller="YoutubeController"> 
    <iframe id="test" width="560" height="315" src="https://www.youtube.com/embed/5tVGei24TdQ" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe> 
    <button type="button" class="btn btn-primary" ng-click="updateYoutubeEmbeds()">YTTest</button> 
 </div> 
</section>

<script>
angular.module('yourAppModule').controller('YoutubeController', ['$scope', '$http', function($scope, $http) {
    $scope.updateYoutubeEmbeds = function() {
        $http.post('/umbraco/surface/YoutubeEmbed/UpdateEmbeds')
            .then(function(response) {
                if (response.data.Success) {
                    // 更新页面内容
                    document.querySelector('.container').innerHTML = response.data.ModifiedContent;
                    // 绑定点击加载逻辑
                    document.querySelectorAll('.youtube-thumbnail-container').forEach(container => {
                        container.addEventListener('click', () => {
                            const videoId = container.dataset.videoId;
                            container.innerHTML = `<iframe width="560" height="315" src="https://www.youtube.com/embed/${videoId}" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>`;
                        });
                    });
                }
            });
    };
}]);
</script>

3. 关键注意事项

  • 不要直接修改视图文件:生产环境中,视图是编译后的,直接修改会导致应用重启,建议把HTML内容存在Umbraco的内容节点字段里(比如Rich Text Editor字段),而不是硬编码在视图中。
  • Razor输出HTML要用@Html.Raw():如果直接输出字符串,Razor会自动转义HTML标签,导致内容无法正常渲染。
  • Cookie合规性:延迟加载iframe的方式可以避免初始页面加载时触发YouTube的Cookie,符合GDPR等数据合规要求。

内容的提问来源于stack exchange,提问作者Evil-E

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 20:42:33