Управляемый базой данных Imagebrowser для Kendo UI для Asp.Net Core - PullRequest
0 голосов
/ 24 апреля 2019

На этот вопрос я сам отвечу. Я потратил пару часов, пытаясь заставить его работать, основываясь на приведенном здесь примере: https://github.com/telerik/ui-for-aspnet-mvc-examples/tree/master/editor/database-image-browser/DatabaseImageBrowser Поскольку я не веду блог, это мой способ документировать это, если другие сталкиваются с тем же сценарием использования, и это может сэкономить им время

Проблема заключается в следующем: как реализовать Imagebrowser, который работает не с локальной папкой, а с базой данных. Пример, предоставленный Telerik, работает с виртуальными папками, хранящимися в одной таблице, и изображениями, связанными в отдельную таблицу, которые связаны с идентификатором папки. Поскольку я не хотел использовать папки, мне нужно было найти способ обойти это. Также: IImageBrowserController предлагает только синхронный интерфейс, что делает его непригодным для асинхронных операций:

public interface IImageBrowserController : IFileBrowserController
{
    IActionResult Thumbnail(string path);
}

public interface IFileBrowserController
{
    ActionResult Create(string path, FileBrowserEntry entry);
    ActionResult Destroy(string path, FileBrowserEntry entry);
    JsonResult Read(string path);
    ActionResult Upload(string path, IFormFile file);
}

Вторая проблема: как преобразовать путь чтения образа из виртуального пути .Image("~/Content/UserFiles/Images/{0}") в маршрут mvc

И, наконец, как реализовать пользовательский контроллер или страницу Razor, чтобы вам не приходилось использовать виртуальные папки в Asp.Net Core.

1 Ответ

1 голос
/ 24 апреля 2019

Прежде всего, создайте интерфейс, подходящий для асинхронных операций:

public interface IImageBrowserControllerAsync
{
    Task<IActionResult> Create(string name, FileBrowserEntry entry);
    Task<IActionResult> Destroy(string name, FileBrowserEntry entry);
    Task<IActionResult> Image(string path);
    Task<JsonResult> Read(string path);
    Task<IActionResult> Thumbnail(string path);
    Task<IActionResult> Upload(string name, IFormFile file);
}

Затем создайте реализацию контроллера.Я опущу некоторые методы, поэтому я не трачу драгоценное время на чтение.Реализация похожа на предоставленные методы:

public class ImageBrowserController : ControllerBase, IImageBrowserControllerAsync
{
    private IImageRepository _repo;
    private const int ThumbnailHeight = 80,
        ThumbnailWidth = 80;

    public ImageBrowserController(IImageRepository repo)
    {
        _repo = repo;
    }

    [Route("Image")]
    public async Task<IActionResult> Image(string path)
    {
        var image = await _repo.GetByName(path);
        if (image != null)
        {
            return File(image.Data, image.ContentType);
        }

        return NotFound("Errormessage");
    }

    //read all images, when the widget loads
    [Route("Read")]
    public async Task<JsonResult> Read(string path)
    {
        var images = await _repo.Get(); // do not return the image data. it is not 
        //needed and will clog up your resources
        var fbe = images.Select(x => new FileBrowserEntry
        {
            Name = x.Name,
            EntryType = FileBrowserEntryType.File
        });
        return new JsonResult(fbe);
    }

    //Create thumbnail using SixLabors.Imagesharp library
    [Route("Thumbnail")]
    public async Task<IActionResult> Thumbnail(string path)
    {
        var image = await _repo.GetByName(path);
        if (image != null)
        {
            var i = SixLabors.ImageSharp.Image
                .Load(image.Data);
            i.Mutate(ctx => ctx.Resize(ThumbnailWidth, ThumbnailHeight));

            using (var ms = new MemoryStream())
            {
                i.SaveAsJpeg(ms);
                return File(ms.ToArray(), image.ContentType);
            }
        }
        return NotFound();
    }

    [Route("Upload")]
    public async Task<IActionResult> Upload(string name, IFormFile file)
    {
        if (file == null || file.Length == 0) return BadRequest();
        using (var ms = new MemoryStream())
        {
            file.CopyTo(ms);
            var img = new Entities.Image
            {
                Name = file.FileName,
                ContentType = file.ContentType,
                Data = ms.ToArray()

            };
            await _repo.CreateImage(img);
            return Ok();
        }
    }
}

А вот конфигурация Imagebrowser / Editor:

@(Html.Kendo().Editor()
        .Name("editor")

        .HtmlAttributes(new { style = "width: 100%;height:440px
        .Tools(tools => tools
            .Clear()
            /*omitted config*/
        )
      .ImageBrowser(ib => ib
          //use actionmethod, controller, route values format
          .Image("Image", "ImageBrowser", new {path = "{0}"}) 
          .Read("Read", "ImageBrowser") // path can be null if you don't use folders
          .Destroy("Destroy", "ImageBrowser")
          .Upload("Upload", "ImageBrowser")
          .Thumbnail("Thumbnail", "ImageBrowser"))
      )

Кто бы это ни читал: надеюсь, этот пример поможет вам сэкономить времяв реализации этого на Asp.Net Core.

Внимание! При чтении всех изображений при загрузке не возвращайте byte[].Kendo хочет только FileBrowserEntry с именем и свойством типа.

Настоятельно советую реализовать кеширование здесь.Создание миниатюр для десятков или сотен изображений на каждой странице загружает огромную нагрузку на вашу инфраструктуру.

...