LoginSignup
68

More than 5 years have passed since last update.

クリップボードの画像ファイルをアップロードする

Last updated at Posted at 2014-12-27

QiitaやGithub のようにWebアプリ上でクリップボードにコピーした画像をペーストコマンドでサーバに直接アップロードする方法。

実装例

DevHubというチャットツールのチャット欄・メモ欄に実装した。
Web上の画像をコピー、または画面キャプチャから直接ペースト機能を使ってファイルアップロードからの表示ができるようになったのでとても便利になった。

以下、動作イメージ。
* クリップボードに画像をコピーした状態でメモ欄に Ctrl-v すると画像ファイルがアップロードされ、パスが返ってくる。
スクリーンショット 2014-12-27 22.17.19.png

  • 編集を終了すると独自のマークダウン処理で画像が表示される。 スクリーンショット 2014-12-27 22.17.39.png

実装手順

  • 貼り付け対象のDOMに 'paste' イベントをバインド
  • pasteイベント処理内でeventから画像を取り出す
  • Ajaxで画像情報をサーバに送信
  • サーバ側でファイルを保存し保存後のパスをクライアントに送信
  • クライアントで保存後のファイルパスを元に画像を表示する

クライアントサイド(js)

pasteイベント発生時にクリップボードの画像をサーバへ送信する。
Ajaxでのアップロード処理は通常のフォームからのファイルアップロードと同様。
(以下のソースは DevHubのソースから抜粋して多少単純化している)

$target.on('paste', function(event){
  // event からクリップボードのアイテムを取り出す
  var items = event.originalEvent.clipboardData.items; // ここがミソ
  for (var i = 0 ; i < items.length ; i++) {
    var item = items[i];
    if (item.type.indexOf("image") != -1) {
      // 画像のみサーバへ送信する
      var file = item.getAsFile();
      upload_file_with_ajax(file);
    }
  }
});

// ファイルアップロード
function upload_file_with_ajax(file){
    var formData = new FormData();
    formData.append('file', file);

    $.ajax('/upload' , {
      type: 'POST',
      contentType: false,
      processData: false,
      data: formData,
      error: function() {
        // アップロードエラー処理
      },
      success: function(res) {
        // アップロード成功処理 res.fileName
      }
    });
  }

サーバサイド(Node)

サーバサイドではクライアントからPOSTに対し画像の保存と保存後ファイルパスの返却を行う。

var fs = require('fs');
var util = require('../lib/util');

exports.post = function(req, res) {
  var tmp_path = req.files.file.path;
  var base_name = req.files.file.name;

  // 画像貼り付けの場合は拡張子を付加する paste_image.xxx
  if (base_name == "blob" && req.files.file.type.indexOf('image') != -1){
    base_name = "paste_image." + req.files.file.type.split('/')[1];
  }

  // 20141114000310_paste_image.png のようなファイル名を生成
  var file_name = util.getFullDateNoSepa(new Date()) + '_' + base_name;

  var target_path = './static/uploads/' + file_name; // 保存先パス
  var access_path = '/uploads/' + file_name; // クライアントへ返すパス

  // ファイルの保存が成功したらレスポンスを返す
  fs.rename(tmp_path, target_path, function(err) {
    if (err) {
      throw err;
    }
    fs.unlink(tmp_path, function() {
      if (err) {
        throw err;
      }
      res.send({fileName: access_path});
      // クライアントでは fileName でファイルパスの取得可能
    });
  });
};

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
68