Создание предпросмотра документа с различными форматами файлов

В статье приведен пример создания возможности предпросмотра документа, версией которого является видеофайл формата mp4.

Пример отображения данных

Рис. 1. Предпросмотр видеофайла в карточке документа

Рис. 2. Предпросмотр видеофайла в popup-окне

Методы расширения (интерфейса) IFilePreviewCreator

Точка расширения (интерфейс) IFilePreviewCreator имеет следующие методы:

/// <summary>
/// Уникальный идентификатор
/// </summary>
Guid Uid { get; }

/// <summary>
/// Отображаемое имя
/// </summary>
string DisplayName { get; }

/// <summary>
/// Расширения файлов
/// </summary>
List<string> Extensions { get; }

/// <summary>
/// Имя главного файла
/// </summary>
/// <param name="file">Файл</param>
/// <returns></returns>
string GetMainFileName(BinaryFile file);

/// <summary>
/// Имя текстового файла
/// </summary>
/// <param name="file">Файл</param>
/// <returns></returns>
string GetTextFileName(BinaryFile file);

/// <summary>
/// Относительный путь до главного файла
/// </summary>
/// <param name="file">Файл</param>
/// <returns></returns>
string GetRelativeMainFileName(BinaryFile file);

/// <summary>
/// Создать превью
/// </summary>
/// <param name="path">Путь</param>
/// <param name="file">Файл</param>
void Create(string path, BinaryFile file);
        
/// <summary>
/// Доступен ли для использования
/// </summary>
/// <param name="file">Файл</param>
/// <returns></returns>
bool IsAvaliable(BinaryFile file);

/// <summary>
/// Имеется ли сгенерированая превью
/// </summary>
/// <param name="file">Файл</param>
/// <returns></returns>
bool HasPreview(BinaryFile file);

/// <summary>
/// Имеется ли сгенерированая превью
/// </summary>
/// <param name="file">Файл</param>
/// <param name="priority">Приоритет</param>
/// <returns></returns>
bool HasPreview(BinaryFile file, long priority);

/// <summary>
/// Получение текстового представления превью для индексации
/// </summary>
/// <param name="file">Файл</param>
/// <returns></returns>
string GetPreviewText(BinaryFile file);

/// <summary>
/// Генерится превью в формате HTML
/// </summary>
/// <returns></returns>
bool EnableGenerateHtml();

Пример класса точки расширения IFilePreviewCreator

[Component]
public class VideoPreviewCreator : IFilePreviewCreator
{
    private readonly Guid _uid = new Guid("{2B94E4DF-BCE2-4b54-AC85-3ABE24BB5F92}");

    public Guid Uid
    {
        get { return _uid; }
    }

    public string DisplayName
    {
        get { return SR.T("Видео файлы (.mp4)"); }
    }

    public List<string> Extensions
    {
        get { return new List<string> { ".mp4" }; }
    }

    public string GetMainFileName(BinaryFile file)
    {
        return file.ContentFilePath;
    }

    public void Create(string path, BinaryFile file)
    {

    }

    public string GetPreviewText(BinaryFile file)
    {
        return null;
    }

    public bool EnableGenerateHtml()
    {
        return false;
    }

    public IRuntimeApplication RuntimeApplication { get; set; }

    public string PreviewDir
    {
        get { return null; }
    }

    public string GetRelativeMainFileName(BinaryFile file)
    {
        return null;
    }

    public virtual string GetTextFileName(string filePreviewDir, BinaryFile file)
    {
        return null;
    }

    public virtual string GetTextFileName(BinaryFile file)
    {
        return null;
    }

    public virtual string GetMainFileName(string filePreviewDir, BinaryFile file)
    {
        return GetTextFileName(filePreviewDir, file);
    }

    public virtual bool IsAvaliable(BinaryFile file)
    {
        var settings = Locator.GetService<PreviewSettingsModule>();
        return settings == null || settings.IsEnabledPreview(this);
    }

    public virtual bool HasPreview(BinaryFile file)
    {
        return HasPreview(file, 5);
    }

    public virtual bool HasPreview(BinaryFile file, long priority)
    {
        return true;
    }

    protected virtual Encoding GetFileEncoding(string filename)
    {
        var fileContent = File.ReadAllBytes(filename);
        return EncodingTools.DetectInputCodepage(fileContent);
    }

}
Примечание
Для реализации данной точки расширения необходима реализация еще одной точки расширения: IFilePreviewCreatorRenderer

Методы расширения (интерфейса) IFilePreviewCreatorRender

Guid Uid { get; }

Type CreatorType { get; }

/// <summary>
/// Рендер (отрисовка Preview)
/// </summary>
/// <param name="helper">Хелпер</param>
/// <param name="file">Файл</param>
/// <returns></returns>
bool Render(HtmlHelper helper, BinaryFile file);

/// <summary>
/// Наименование инициализующей функции JavaScript, которая инициализирует отрисовку Preview (До отрисовки самого Preview)
/// </summary>
/// <param name="uniquePrefix">Уникальный префикс</param>
/// <returns>Наименование инициализирующей функции с префиксом</returns>
string InitFunctionName(string uniquePrefix);

/// <summary>
/// Наименование onClose функции JavaScript
/// </summary>
/// <param name="uniquePrefix">Уникальный префикс</param>
/// <returns>Наименование onClose функции с префиксом</returns>
string CloseFunctionName(string uniquePrefix);

/// <summary>
/// Наименование для функции JavaScript расчета тулбара (если таковой имеется), например, для расчета его позиции на странице
/// </summary>
/// <param name="uniquePrefix">Уникальный префикс</param>
/// <returns>Наименование для функции расчета тулбара с префиксом</returns>
string CalcToolbarFunctionName(string uniquePrefix);

Пример класса точки расширения IFilePreviewCreatorRender

[Component]
public class VideoPreviewCreatorRenderer : IFilePreviewCreatorRenderer
{
    public static Guid UID = new Guid("{BF13D8F8-2AC4-457b-A96A-2992182AEEB5}");

    public Guid Uid
    {
        get { return UID; }
    }

    public Type CreatorType
    {
        get { return typeof(VideoPreviewCreator); }
    }

    public virtual string InitFunctionName(string uniquePrefix)
    {
        return null;
    }

    public virtual string CloseFunctionName(string uniquePrefix)
    {
        return "ClosePreview";
    }

    public virtual string CalcToolbarFunctionName(string uniquePrefix)
    {
        return null;
    }

    public virtual bool Render(HtmlHelper helper, BinaryFile file)
    {
        var previewService = Locator.GetServiceNotNull<IFilePreviewService>();
        var creator = previewService.GetPreviewCreator(file);
        if (creator != null)
        {
            var model = new BaseFilePreviewInfo
            {
                File = file,
                PreviewCreator = creator
            };

            helper.RenderPartial("Video", model);
        }
        return true;
    }
}

Как можно заметить из приведенного примера кода, Рендер (отрисовка Preview) ссылается на Ваше представление Video, в котором находится разметка с видеофайлом. Представление необходимо расположить по пути Веб-часть_Вашего_Модуля\Views\Shared\. Пример кода Video.cshtml:

@model EleWise.ELMA.Web.Mvc.Models.Previews.BaseFilePreviewInfo
@using EleWise.ELMA

@{
    var fileUid = UIExtensions.PrepareId(Model.File.Id ?? Model.File.Uid.ToString());
    var uniqueGlobalPrefix = ViewData["UniqueGlobalPrefix"] ?? string.Empty;
    var videoid = String.Format("Video_{0}", Model.File.Uid);
    var previewToolbarId = string.Format("previewImgToolbar_{0}{1}", uniqueGlobalPrefix, fileUid);
    var closePreviewFunc = "ClosePreview";
}

<div id="@previewToolbarId" style="text-align:center; height:auto; width:auto;">
    <video id=@videoid controls preload="auto">
        <source src="@(Url.Action("Download", "BinaryFiles", new {area = "EleWise.ELMA.SDK.Web", id = Model.File.Uid}))" type=’video/mp4’ />
        <p>@SR.T("Чтобы воспроизвести данный файл удостоверьтесь, что ваш браузер поддерживает HTML5")</p>
    </video>
</div>

<script type="text/javascript">
    $(’#btnPrint’).next().remove();
    $(’#btnPrint’).remove();
    
    var video = document.getElementById("@videoid");
    function @(closePreviewFunc)() {
        video.pause();
    }
</script>

Предпросмотр документов доступен не только в карточке документов, но и повсеместно в системе, например, при нажатии на документ в ленте сообщений. В этом случае Вам будет предложено открыть документ прямо в браузере и документ откроется в popup-окне. В этом popup-окне будут убраны 2 кнопки: распечатать и полный экран, а также реализована остановка видео при закрытии popup-окна.

Важное замечание
Работа данной реализации будет осуществляться только в браузерах, поддерживающих html5 (например, IE 9.0, Chrome 4.0, Firefox 3.5, Safari 4.0). В каждом из этих браузеров будет собственный проигрыватель видеофайлов. Если формат видео не поддерживается плеером, например, расширение файла .avi переименовали в .mp4, то в зависимости от браузера будет отображено соответствующее оповещение, например, в IE9.0 будет просто «Ошибка», в Firefox будет «Видео в поддерживаемом формате и типе не найдено», а в Chrome кнопки будут заблокированы

С помощью данного примера можно реализовать воспроизведение аудиофайлов, для этого в представлении необходимо заменить тег video на тег audio,а также заменить поддерживаемый точкой расширения формат файла. Подробнее о поддерживаемых аудио и видео форматах, а также поддержке браузеров Вы можете прочитать здесь и здесь.

Ссылки на элементы API

IFilePreviewCreator
IFilePreviewCreatorRenderer

Прикрепленные файлы