2 years ago by: matt

Couldn't get this working right out of the box due to some changed syntax/callbacks on summernote so here's some quick code samples on how to get image upload working for summernote 0.7. Keep an eye on the summernote insertion API for any changes in future:

http://summernote.org/deep-dive/#insertimage

Unless you have manually disabled csrf, Laravel will be expecting the post request to also submit the csrf-token for your session. In my case I have added it into my blade template "header" section on the form.

    <meta name="csrf-token" content="{{ csrf_token() }}"/>

Along with that you need to add it to the ajaxSetup method before the $(document).ready definition:

$.ajaxSetup({
    headers: {
        'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
    }
});

Now you need to define the callback for "onImageUpload" when you instantiate summernote:

$('#summernote').summernote({
    height: 300,
    focus: true,
    callbacks: {
        onImageUpload: function (files) {
            uploadImage(files[0]);
        }
     }
});

In this case it triggers a function called uploadImage() which for me looks like:

function uploadImage(file) {
    data = new FormData();
    data.append("file", file);
    $.ajax({
        data: data,
        type: 'POST',
        url: '/api/image',
        cache: false,
        contentType: false,
        processData: false,
        success: function (url) {
            $('#summernote').summernote('insertImage', url);
        }
    });
}

In my case I post to an endpoint at /api/image which if successful returns the url of the uploaded image which then gets passed to summernotes insertion API thorugh "insertImage".

Thats it for the frontend side. On the laravel side of things my implementation consisted of the following:

App\Http\Routes.php

I have placed my image routes under the /api prefix only because in future I may want to have control over the individual requests coming in (re-sizing/limiting etc..). You could simply serve them directly through nginx/apache without going through PHP like I have done here.

Route::group(['prefix' => 'api'], function ()
{
    Route::post('image', ['middleware' => 'auth', 'uses' => 'Api\ImageController@store']);
    Route::get('image/{image}', 'Api\ImageController@view');
});

Make sure if you only want authenticated users to be able to post images to use the 'auth' as middleware for the post route.

App\Http\Controllers\Api\ImageController

<?php


namespace App\Http\Controllers\Api;


use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Response;

class ImageController extends Controller
{

    public function view($image)
    {
        $path = storage_path() . '/uploads/' . $image;

        if (File::exists($path))
        {
            $filetype = File::type($path);
            $response = Response::make(File::get($path), 200);
            $response->header('Content-Type', $filetype);

            return $response;
        }

        return false;
    }

    public function store(Request $request)
    {
        $extension = $request->file('file')->getClientOriginalExtension();
        $fileName = uniqid() . '.' . $extension;
        $destination = storage_path() . '/uploads';

        $request->file('file')->move($destination, $fileName);

        return url(url('api/image/' . $fileName));
    }
}

I am keeping images under storage/uploads so you could also make use of the Storage:: facade instead of using the $request->file methods.

Keep in mind the controller above does not have any sort of validation on it at the moment.