Summernote image upload from URL
Asked Answered
P

1

6

I'm using summernote html text editor on my site. I want to download images to my server when user put an image url to Image URL area then press to Insert Image button.

Currently summernote only get image's source for src attribute. I want to store images on my own Amazon S3 Bucket or VPS.

There are many docs about summernote image upload but all of them for upload from pc not from URL.

How can I overwrite this feature? enter image description here


Image dialog enter image description here

Procora answered 26/2, 2017 at 2:7 Comment(3)
Pass the URL in an ajax call, or the like, to your server and then use your server side technology (looks like php from your tagging above) to download, and subsequently send to Amazon S3 - although, you might be able to go direct to the Amazon S3 from the browser using Amazon S3 REST API, docs.aws.amazon.com/AmazonS3/latest/API/sigv4-post-example.htmlBrandt
Use Ckeditor this is better.Caracal
Upload images with ckeditor github.com/fxstar/CKeditorUploadCaracal
M
1

So since you are not able to read dataUrl of cross-origin images in your client-side script the decision is to get url from Image URL area and send it to your backend. There you may use a simple php script to download the image.

The example includes both client and backend codes. Both tested. All you need is to put these two scripts to one of your web server's directories and give it a try.

index.html

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>Summernote</title>
        <!-- include libraries(jQuery, bootstrap) -->
        <link href="http://netdna.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.css" rel="stylesheet">
        <script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.js"></script> 
        <script src="http://netdna.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.js"></script> 

        <!-- include summernote css/js-->
        <link href="http://cdnjs.cloudflare.com/ajax/libs/summernote/0.8.2/summernote.css" rel="stylesheet">
        <script src="http://cdnjs.cloudflare.com/ajax/libs/summernote/0.8.2/summernote.js"></script>
    </head>
    <body>
        <div id="summernote">Hello Summernote</div>
        <script type="text/javascript">
            $(document).ready(function() {
                $('#summernote').summernote();
                $('button[data-original-title="Picture"]').click(function(){
                    // Set handler on Inset Image button when dialog window is opened  
                    $('.modal-dialog .note-image-btn').one('click', function(e) {
                        // Get Image URL area
                        var imageUrl = $('.modal-dialog .note-image-url').val();
                        // Send it to your backend
                        $.ajax({
                            url: "image_loader.php",
                            data: "url="+imageUrl,
                            type: "POST",
                            dataType: 'json'
                        }).success(function(data) {
                            if (typeof data[0] === 'string') {
                                $('img[src="'+imageUrl+'"]').attr('src', data);
                            } else {
                                // What to do if image downloading failed
                                window.alert('oops');
                            }
                        }).error(function() {
                            // What to do if ajax request failed
                            window.alert('oops');
                        });
                    });
                });  
            });
        </script>
    </body>
</html>

image_loader.php

<?php
if ($_POST['url']) {
    // Here you'd better put some logic to check that $_POST['url'] is a correct url before use it
    $image = file_get_contents($_POST['url']);

    if ($image) {
        // Put downloaded image on your server
        $file = fopen('imagename.jpeg', 'w');
        fwrite($file, $image);
        fclose($file);
    }

    /** 
     * Now your code needs to echo one of the following:
     * string Url of an uploaded image on your server
     * bool False if it failed
     * 
     * To avoid bool to string conversion during output response needs to be sent as JSON
     */
    $response = ($image) ? array('/PATH_TO_IMAGE_DIRECTORY_IF_NEEDED/imagename.jpeg') : array(false);
    echo json_encode($response);
}

For example with this image https://imgsnap.com/images/2015/02/23/abstract_0005.jpg

UPDATE (to your comment about img styling)

Put the following line in summernote.js to trigger a special event when image url has been handled by the editor.

$(document).trigger('imageUrlInserted', src);

Put it on line 4095 (according to my version of file) inside of insertImage() method before

$image.css('width', Math.min($editable.width(), $image.width()));

Now in index.php inside of

$('.modal-dialog .note-image-btn').one('click', function(e) {
...

...
});

replace all the code with this

// Get Image URL area
var imageUrl = $('.modal-dialog .note-image-url').val();
// Send it to your backend after the image been handled by the editor
$(document).on('imageUrlInserted', function(e, sourceUrl) {
    if (sourceUrl === imageUrl) {
        $.ajax({
            url: "image_loader.php",
            data: "url="+imageUrl,
            type: "POST",
            dataType: 'json'
        }).success(function(data) {
            if (typeof data[0] === 'string') {
                $('img[src="'+imageUrl+'"]').attr('src', data).removeAttr('style');
            } else {
                // What to do if image downloading failed
                window.alert('oops');
            }
        }).error(function() {
            // What to do if ajax request failed
            window.alert('oops');
        });
    }
});
Margo answered 9/3, 2017 at 22:21 Comment(10)
This is nice approach to my question. Will it add this image to summernote editor's current content area. Now im not at home. İ will try it:)Procora
"Will it add this image to summernote editor's current content area." - yes it will because it does not change summernote's logic. Just attaches two additional handlers to it's nodes.Margo
How to change summernote's img src="" value to uploaded image's path. Now with this solution I can dowload image to server but summernote's src path still has original remote URLProcora
See updates in the answer on lines 13-21 in image_loader.php and 34-44 in index.php. Note that if you pass invalid url to file_get_contents() it will throw a warning so you will not get correct json response on client side. To avoid this use @file_get_contents() in your dev code. In production you will switch off displaying errors so warning will no longer be a problem.Margo
Will it replace only new uploaded image's src path? What if there are more than one image on summernote's content area?Procora
"Will it replace only new uploaded image's src path?" - it will replace what it find.Margo
"What if there are more than one image on summernote's content area?" - if you change path (in editor) to every uploaded image then there will be no images with similar paths at one moment in editor (of course if you save each image on server with different name). But if uploading fails then image URL will stay original and you need to decide what to do with it (I've highlighted two points where to do it in index.php by comments, see lines 39 and 43). For example you can erase image if something went wrong...Margo
Working correctly!! But when I add image summernote, it adds width attribute to image like style="width: 347px;". How to I prevent it? Because my all images have width:100% with a css rule.Procora
You can easily change it using JS. For example, to remove summernote's styling once after you've uploaded an image to your server you can chain additional Jquery handler to line 37 so it will look like $('img[src="'+imageUrl+'"]').attr('src', data).removeAttr('style');. In index.php you are using asynchronous request and it's success block will be executed after any synchronous logic attached to Insert Image button.Margo
But after looking through the summernote.js file I realized that it uses async logic to handle image url you post to it. I've added a quick workaround that does not bother editor's logic and should help to avoid collisions with multiple async requests conducted at the same time.Margo

© 2022 - 2024 — McMap. All rights reserved.