CefSharp 75.1.143 местное .WebM видео не загружается - PullRequest
0 голосов
/ 21 января 2020

Я пытаюсь создать список воспроизведения видео на основе HTML, используя CefSharp версии 75.1.143, и я не могу загрузить локальные файлы, CefSharp работает с протоколом file: // и с файлами, размещенными в Интернете (пример: http://clips.vorwaerts-gmbh.de/VfE.webm ).

Я уже реализую свой собственный CustomFolderSchemeHandlerFactory и регистрирую его в настройках и уже отвечаю заголовком Content-Range и кодом состояния 206, но видео не загружено и запрос прерывается без полной загрузки видео.

Регистрация:

            settings.RegisterScheme(new CefCustomScheme
            {
                SchemeName = "localfiles",
                DomainName = "vw",
                SchemeHandlerFactory = new FolderSchemeHandlerFactory(rootFolder: @".\bundle\", hostName: "vw", defaultPage: "index.html"),
                IsCSPBypassing = true,
                IsStandard = true
            });

            settings.RegisterScheme(new CefCustomScheme
            {
                SchemeName = "localresources",
                DomainName = "vwres",
                SchemeHandlerFactory = new CustomFolderSchemeHandlerFactory(rootFolder: helperService.GetResourcesFolder(), hostName: "vwres"),
                IsCSPBypassing = true,
                IsStandard = true
            });

Код:

public class CustomFolderSchemeHandlerFactory : ISchemeHandlerFactory
    {
        private string rootFolder;
        private string defaultPage;
        private string schemeName;
        private string hostName;
        private FileShare resourceFileShare;

        /// <summary>
        /// Initialize a new instance of FolderSchemeHandlerFactory
        /// </summary>
        /// <param name="rootFolder">Root Folder where all your files exist, requests cannot be made outside of this folder</param>
        /// <param name="schemeName">if not null then schemeName checking will be implemented</param>
        /// <param name="hostName">if not null then hostName checking will be implemented</param>
        /// <param name="defaultPage">default page if no page specified, defaults to index.html</param>
        public CustomFolderSchemeHandlerFactory(string rootFolder, string schemeName = null, string hostName = null, string defaultPage = "index.html", FileShare resourceFileShare = FileShare.Read)
        {
            this.rootFolder = Path.GetFullPath(rootFolder);
            this.defaultPage = defaultPage;
            this.schemeName = schemeName;
            this.hostName = hostName;
            this.resourceFileShare = resourceFileShare;

            if (!Directory.Exists(this.rootFolder))
            {
                try
                {
                    Directory.CreateDirectory(this.rootFolder);
                }
                catch (Exception)
                {
                    MessageBox.Show("There was an error creating your folder (" + this.rootFolder + "), be sure to have all the necessary privileges to run this software", "InfoHub Cloud Error", MessageBoxButtons.OK);
                    Application.Exit();
                }
            }
        }

        IResourceHandler ISchemeHandlerFactory.Create(IBrowser browser, IFrame frame, string schemeName, IRequest request)
        {
            if (this.schemeName != null && !schemeName.Equals(this.schemeName, StringComparison.OrdinalIgnoreCase))
            {
                return ResourceHandler.ForErrorMessage(string.Format("SchemeName {0} does not match the expected SchemeName of {1}.", schemeName, this.schemeName), HttpStatusCode.NotFound);
            }

            var uri = new Uri(request.Url);

            if (this.hostName != null && !uri.Host.Equals(this.hostName, StringComparison.OrdinalIgnoreCase))
            {
                return ResourceHandler.ForErrorMessage(string.Format("HostName {0} does not match the expected HostName of {1}.", uri.Host, this.hostName), HttpStatusCode.NotFound);
            }

            //Get the absolute path and remove the leading slash
            var asbolutePath = uri.AbsolutePath.Substring(1);

            if (string.IsNullOrEmpty(asbolutePath))
            {
                asbolutePath = defaultPage;
            }

            var filePath = WebUtility.UrlDecode(Path.GetFullPath(Path.Combine(rootFolder, asbolutePath)));

            //Check the file requested is within the specified path and that the file exists
            if (filePath.StartsWith(rootFolder, StringComparison.OrdinalIgnoreCase) && File.Exists(filePath))
            {
                var fileExtension = Path.GetExtension(filePath);

                if (fileExtension.ToLower() == ".webm" || fileExtension.ToLower() == ".ogv") //Gestione speciale dei video
                {
                    return new CustomFolderSchemeHandler(rootFolder);
                }

                var mimeType = ResourceHandler.GetMimeType(fileExtension);
                var stream = new FileStream(filePath, FileMode.Open, FileAccess.Read, resourceFileShare);
                return ResourceHandler.FromStream(stream, mimeType);
            }

            return ResourceHandler.ForErrorMessage("File Not Found - " + filePath, HttpStatusCode.NotFound);
        }
    }

CustomFolderSchemeHandler:

internal class CustomFolderSchemeHandler : ResourceHandler
    {
        private string rootFolder;

        public CustomFolderSchemeHandler(string rootFolder)
        {
            this.rootFolder = rootFolder;
        }

        public override CefReturnValue ProcessRequestAsync(IRequest request, ICallback callback)
        {
            var uri = new Uri(request.Url);
            var fileName = uri.AbsolutePath;

            var filePath = HttpUtility.UrlDecode(Path.Combine(rootFolder, fileName.Substring(1).Replace("/", "\\")));
            var fileInfo = new FileInfo(filePath);
            var fileLength = fileInfo.Length;
            var fileLastModifyDate = File.GetLastWriteTime(filePath);

            var range = request.Headers["Range"];
            var rangeBottom = 0;
            var rangeTop = fileLength - 1;
            if (!string.IsNullOrEmpty(range))
            {
                range = range.Replace("bytes=", "");

                var rangeValues = range.Split(new string[] { "-" }, StringSplitOptions.RemoveEmptyEntries);
                rangeBottom = int.Parse(rangeValues[0]);
                if (rangeValues.Length > 1)
                    rangeTop = int.Parse(rangeValues[1]);
            }

            var fileBytes = ReadFileBytes(filePath, rangeBottom, (int)(rangeTop - rangeBottom));

            Task.Run(() =>
            {
                using (callback)
                {
                    Stream stream = new MemoryStream((int)(rangeTop - rangeBottom));
                    stream.Write(fileBytes, 0, fileBytes.Length);
                    stream.Position = 0;

                    Headers.Add("Accept-Ranges", "bytes");
                    Headers.Add("Access-Control-Allow-Origin", "*");
                    Headers.Add("Last-Modified", fileLastModifyDate.ToString("R"));
                    Headers.Add("Content-Length", (rangeTop - rangeBottom + 1).ToString());
                    Headers.Add("Content-Type", "video/mp4");
                    Headers.Add("Content-Range", "bytes " + rangeBottom + "-" + rangeTop + "/" + fileLength);

                    ResponseLength = stream.Length;
                    MimeType = "video/webm";
                    StatusCode = (int)HttpStatusCode.PartialContent;
                    StatusText = "Partial Content";
                    Stream = stream;

                    callback.Continue();
                }
            });

            return CefReturnValue.ContinueAsync;
        }

        private static byte[] ReadFileBytes(string path, int offset, int count)
        {
            using (var file = File.OpenRead(path))
            {
                file.Position = offset;
                offset = 0;
                byte[] buffer = new byte[count];
                int read;
                while (count > 0 && (read = file.Read(buffer, offset, count)) > 0)
                {
                    offset += read;
                    count -= read;
                }
                if (count < 0) throw new EndOfStreamException();
                return buffer;
            }
        }
    }

Кто-нибудь знает как решить эту проблему?

...