WYSIWYGのエディタSummernoteではファイルアップロード機能を実装できる
Data URI schemeとFile Upload
Bootstrap3でデザインされたWYSIWYGのエディタSummernoteに画像アップロード機能を実装する。
SummernoteをCakePHPで利用する
SummernoteにはデフォルトでData URI schemeで画像ファイルをエディタに貼り付けることが可能。実際に画像を貼り付けて、HTMLのソースコードを確認してみたのが下の画像の状態になる。
Data URI schemeの方法を用いると画像をサーバ側にアップロードすることなく、画像をすべてエンコードしてテキスト状態にして貼り付けるため、画像を参照するためのHTTPリクエストが発生しないというメリットがある。
File Upload方式にて画像を管理したい場合には、SummernoteのonImageUploadコールバックを利用して実装することが可能。
CakePHPのSummernoteにFile Upload機能を実装
onImageUploadコールバックを利用すればローカルの画像を選択したタイミングでサーバ側へのファイルアップロード処理を挿入することが可能で、そのヒントが下のURLに書かれている。
https://github.com/HackerWins/summernote/issues/72
layoutのjs
CakePHPのlayoutのjsを下のように変更した。Ajaxのリクエスト先は、
/summernote
にしてある。
サーバサイドで画像サイズのチェックを行い、規定のサイズを超えていた場合はエラーとするため、errorコールバックを設定してある。
$(document).ready(function() { $('#summernote').summernote({ onImageUpload: function(files, editor, welEditable) { sendFile(files[0], editor, welEditable); }, }); }); function sendFile(file, editor, welEditable) { data = new FormData(); data.append("file", file); $.ajax({ data: data, type: "POST", url: "/summernote", cache: false, contentType: false, processData: false, beforeSend: function() { $('#error').html(""); $('#loading').html(""); $('#loading').html("<img src='http://test.local/images/loading.gif' />"); }, success: function(url) { editor.insertImage(welEditable, url); }, error: function(response){ $('#error').html(response.responseText); }, complete: function() { $('#loading').html(""); }, }); }
Controller側で画像のサイズチェック
/summernote
へのリクエストをAjaxか通常のHTTPリクエストか判定した上で、Ajaxリクエストの場合には画像のサイズチェックを行っている。規定のサイズ以下の場合は、画像をアップロードし、サイズを超えている場合にはHTTPのエラーコードとメッセージをレスポンスするようにしたのが下のコード
public function summernote() { if( !$this->request->is('ajax') ) { $this->layout = "summernote"; } else { $tmp_file = $_FILES["file"]["tmp_name"]; if( filesize($tmp_file) > 500000 ) { header("HTTP/1.0 404 Not Found"); echo '<p>サイズオーバーです</p>'; exit(); } else { $name = $this->randomString(); $ext = explode('.',$_FILES['file']['name']); $filename = $name.'.'.$ext[1]; $destination = '/path/to/images/'.$filename; $location = $_FILES["file"]["tmp_name"]; move_uploaded_file($location, $destination); echo 'http://test.local/images/'.$filename; exit(); } } } public function randomString() { return md5(rand(100, 200)); }
Viewには空のHTMLを用意しておく
Viewには一時的に表示されるローディング画像とエラーメッセージを表示する空のHTMLを追加した。
<textarea id="summernote"></textarea> <aside id="error"></aside> <aside id="loading"></aside>
ローディング画像とエラーの内容は、Ajaxオブジェクトのbeforesendコールバックで表示/非表示を制御している。
ファイルアップロードのHTMLソース
ファイルアップロード方式であれば下のようにHTMLのソースは完結な状態になる。
- Data URI scheme
- File Upload
双方の方式で一長一短あるが、Summernoteでは両方の方式に無理なく対処することが可能。