Как загрузить и внедрить изображение в tinymce 4 с помощью Asp.net MVC

Так как не существует абсолютно современного способа загрузки изображений на tinymce в .net бесплатно, я подумал о добавлении ввода для загрузки файлов. в html, затем загрузите его на сервер с помощью ajax, а затем включите файл в редакторе tinymce.

Проблема заключается в том, чтобы ввести изображение в tinymce, я не знаю, как...

Там в любом случае?


person Vahid Amiri    schedule 09.11.2015    source источник
comment
Да, есть способ, мой последний проект сделал это, я могу опубликовать код сегодня вечером, если к тому времени никто не ответил, не припоминаю, как это было достигнуто.   -  person Daniel Hoffmann-Mitscherling    schedule 10.11.2015
comment
Я только что сделал это, и он отлично работает! см. мой другой пост (ответ)   -  person Vahid Amiri    schedule 10.11.2015


Ответы (5)


Хорошо, Micro$oft или кто-то еще должен что-то с этим сделать, а пока вот результат многочасовой отладки:

В этом решении используется функция прямой загрузки (уже есть в Tinymce, но отключена по умолчанию), и с помощью некоторого хака jquery мы вставляем изображение в текстовую область.

Изменение размеров должно быть сделано после вставки изображения. В последних версиях Tinymce они также добавили несколько хороших инструментов для редактирования изображений, которые также работают с этим методом.

Теперь код:

Это действие, которое необходимо поместить в контроллер: (обратите внимание на маршрутизацию)

public string Upload(HttpPostedFileBase file)
    {
        string path;
        string saveloc = "~/Images/";
        string relativeloc = "/Images/";
        string filename = file.FileName;

        if (file != null && file.ContentLength > 0 && file.IsImage())
        {
            try
            {
                path = Path.Combine(HttpContext.Server.MapPath(saveloc), Path.GetFileName(filename));
                file.SaveAs(path);
            }
            catch (Exception e)
            {
                return "<script>alert('Failed: " + e + "');</script>";
            }
        }
        else
        {
            return "<script>alert('Failed: Unkown Error. This form only accepts valid images.');</script>";
        }

        return "<script>top.$('.mce-btn.mce-open').parent().find('.mce-textbox').val('" + relativeloc + filename + "').closest('.mce-window').find('.mce-primary').click();</script>";
    }

И это полный код для Tinymce, он сгенерирует текстовое поле и пару скрытых полей. Он также создаст экземпляр tinymce с включенными некоторыми плагинами.

    <iframe id="form_target" name="form_target" style="display:none"></iframe>

<form id="my_form" action="/admin" target="form_target" method="post" enctype="multipart/form-data" style="width:0;height:0;overflow:hidden">
    <input name="file" type="file" onchange="$('#my_form').submit();this.value='';">
</form>
<script type="text/javascript">
tinymce.init({
    selector: "textarea",
    theme: "modern",
    plugins: [
        "advlist autolink lists link image charmap print preview hr anchor pagebreak",
        "searchreplace wordcount visualblocks visualchars code fullscreen",
        "insertdatetime media nonbreaking save table contextmenu directionality",
        "emoticons template paste textcolor colorpicker textpattern imagetools"
    ],
    toolbar1: "insertfile undo redo | styleselect | bold italic | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link image",
    toolbar2: "print preview media | forecolor backcolor emoticons | ltr rtl",
    image_advtab: true,
    templates: [
        {title: 'Test template 1', content: 'Test 1'},
        {title: 'Test template 2', content: 'Test 2'}
    ],
    file_browser_callback: function(field_name, url, type, win) {
    if(type=='image') $('#my_form input').click();
}
});
</script>

<textarea id="my_editor" class="mceEditor">This will be an editor.</textarea>

Вам нужно создать папку с именем "Изображения" в корне вашего проекта для загрузки изображений. Вам также потребуется файл Tinymce js и jquery.

Измените действие формы в соответствии с вашими настройками!!!

Вы также можете использовать помощники html. Мне они не нравятся. но продолжайте и используйте их вместо этой формы ручной работы, если хотите.

Идея взята из здесь, но это было сделано на питоне, поэтому я переписал его для работы с ASP.NET MVC5 и последней версией TinyMCE.

Я продолжу работать над этим в ближайшие несколько дней и при необходимости отредактирую этот ответ.

person Vahid Amiri    schedule 09.11.2015
comment
Здравствуйте, не могли бы вы мне немного помочь, чтобы понять соответствие полей и форм в javascript? Я имею в виду, что мне нужно указать в field_name? Мне удается отобразить значок, но он неактивен. Спасибо - person touinta; 18.04.2016
comment
@touinta, я тестировал этот код на TinyMCE 4.2, и он отлично работает, не уверен насчет других версий. Какую версию вы используете? - person Vahid Amiri; 18.04.2016
comment
Где вы используете действие «Загрузить»? В вашем js-коде нет URL-адреса, указывающего на это действие. - person VincentZHANG; 01.11.2016
comment
@VincentZHANG После iframe есть тег form и атрибут action, который должен указывать на ваш метод действия. В приведенном выше коде он указывает на /admin - person Vahid Amiri; 01.11.2016
comment
@ VSG24 Спасибо, это хорошее решение, кажется, оно отлично работает с TinyMCE 4.4.3 и MVC 5. - person VincentZHANG; 01.11.2016

Я сделал это в TinyMCE 4.3.10.

В файле tinymce.init укажите следующие параметры:

paste_data_images: true,
images_upload_url: '/YourController/UploadImage',
images_upload_base_path: '/some/basepath'

В коде CSharp:

public ActionResult UploadImage(HttpPostedFileBase file)
{
    file.SaveAs("<give it a name>");
    return Json(new { location = "<url to that file>" });
}

Вы должны иметь возможность копировать и вставлять изображение в текстовое поле (странно, перетаскивание больше не работает).

person s k    schedule 23.04.2016
comment
Да, это работает. IIRC в вашем обработчике file_picker_callback определяет, является ли это локальным файлом. Прочтите, закодируйте его с помощью Base64, а затем вставьте как встроенное изображение с помощью insertContent(). Приведенный выше код все равно будет вызываться. Я обновлю свой ответ позже завтра. - person s k; 23.04.2016
comment
Я использую 4.4.3, и эта конфигурация не показывает кнопку просмотра файла в диалоговом окне изображения. - person VincentZHANG; 01.11.2016

это мой конфиг для последней версии tinymce..

File_browser_callback устарел

.. и это работает .. это работает при копировании, вставке изображения. Я еще не пробовал с менеджером загрузки файлов

         automatic_uploads: true, << auto run your upload script

         images_upload_url: 'ImageUpload', <<your upload, I'm using mvc and I'm routing to "ImageUpload"

        images_reuse_filename:true, << this is where the return json from your code i had a hard time finding this out.  

       file_picker_types: 'image', << type where the upload will appear images dialog,link or file

        //custom file picker       
        file_picker_callback: function (cb, value, meta) {
        var input = document.createElement('input');
        input.setAttribute('type', 'file');
        input.setAttribute('accept', 'image/*');

        // Note: In modern browsers input[type="file"] is functional without 
        // even adding it to the DOM, but that might not be the case in some older
        // or quirky browsers like IE, so you might want to add it to the DOM
        // just in case, and visually hide it. And do not forget do remove it
        // once you do not need it anymore.

        input.onchange = function () {
            var file = this.files[0];

            // Note: Now we need to register the blob in TinyMCEs image blob
            // registry. In the next release this part hopefully won't be
            // necessary, as we are looking to handle it internally.
            var id = 'blobid' + (new Date()).getTime();
            var blobCache = tinymce.activeEditor.editorUpload.blobCache;
            var blobInfo = blobCache.create(id, file);
            blobCache.add(blobInfo);
            console.log(id);
            console.log(blobCache);
            // call the callback and populate the Title field with the file name
            cb(blobInfo.blobUri(), { title: file.name });
            console.log(meta.filetype);



        };

        input.click();


    },
person CyberNinja    schedule 06.01.2017

Я работаю в веб-приложении JSF/Java, и этот код в tynymce.init javascript ниже отлично работал для меня. Картинки сохраняются в середине текстового поля (полагаю). Я думаю, что нет необходимости в дополнительном коде

tinymce.init({
      selector: "textarea",
      browser_spellcheck: true,
      paste_data_images: true,
      plugins: [
        "advlist autolink autosave link image lists charmap print preview hr anchor pagebreak spellchecker",
        "searchreplace wordcount visualblocks visualchars code fullscreen insertdatetime media nonbreaking",
        "table contextmenu directionality template textcolor paste fullpage textcolor colorpicker textpattern"
      ],

      toolbar1: "bold italic underline strikethrough | alignleft aligncenter alignright alignjustify | formatselect fontselect fontsizeselect",
      toolbar2: "cut copy paste | searchreplace | bullist numlist | outdent indent blockquote | undo redo | link unlink anchor image code | insertdatetime preview | forecolor backcolor",
      toolbar3: "table | hr removeformat | subscript superscript | charmap emoticons | print fullscreen | ltr rtl | spellchecker | visualchars visualblocks nonbreaking template pagebreak restoredraft",

      menubar: false,
      image_advtab: true,
      toolbar_items_size: 'small',

      file_picker_callback: function(callback, value, meta) {
          if (meta.filetype == 'image') {
                var inputFile = document.createElement("INPUT");
                inputFile.setAttribute("type", "file");
                inputFile.setAttribute("style","display: none");
                inputFile.click();
                inputFile.addEventListener("change", function() {
                var file = this.files[0];
                var reader = new FileReader();
                reader.onload = function(e) {
                  callback(e.target.result, {
                    alt: ''
                  });
                };
                reader.readAsDataURL(file);
             });
          }
        },

      insertdatetime_dateformat: "%d/%m/%Y",
      insertdatetime_timeformat: "%H:%M:%S",
      language: 'pt_BR',
    });
person Dustan Cardoso    schedule 07.04.2017

HTML

API_KEY — замените на свой для селектора tinymce — замените контроллер MVC в области «Управление»

  <script src="https://cdn.tiny.cloud/1/API_KEY/tinymce/5/tinymce.min.js"></script>
    <script>
        tinymce.init({
            selector: '#Body',
            menubar: ' edit view insert format tools table',
            toolbar: 'undo redo | bold italic underline strikethrough | fontselect fontsizeselect formatselect | alignleft aligncenter alignright alignjustify | outdent indent |  numlist bullist  | forecolor backcolor removeformat | emoticons | fullscreen  | image media  link | code',
            plugins: 'code importcss  searchreplace autolink   visualblocks visualchars fullscreen image link media   codesample table charmap hr  nonbreaking anchor toc insertdatetime advlist lists  wordcount   imagetools textpattern noneditable   charmap   quickbars  emoticons',
            contextmenu: "link image imagetools table",
            image_advtab: true,
            toolbar_sticky: true,
            images_upload_url: '/Control/Home/UploadImage',
            paste_data_images: true,
        });
    </script>

С#

namespace Project.Areas.Control.Controllers
{
    [Authorize(Roles = "admin")]
    public class HomeController : WebBaseController
    {

        [HttpPost]
        public JsonResult UploadImage(HttpPostedFileBase file)
        {
            var uploadsPath = HostingEnvironment.MapPath($"/uploads");
            var uploadsDir = new DirectoryInfo(uploadsPath);
            if (!uploadsDir.Exists)
                uploadsDir.Create();

            var imageRelativePath = $"/uploads/{DateTime.Now:yyyy-MM-dd_HH-mm-ss}.jpg";
            var imageAbsPath = HostingEnvironment.MapPath(imageRelativePath);
            var imageBytes = file.InputStream.ReadToEnd();
            System.IO.File.WriteAllBytes(imageAbsPath, imageBytes);
            return Json(new { location = imageRelativePath });
        }
.....

Метод расширения

public static byte[] ReadToEnd(this Stream input)
        {
            using (MemoryStream ms = new MemoryStream())
            {
                input.CopyTo(ms);
                return ms.ToArray();
            }
        }
person Paul    schedule 18.11.2019