アップロード前にチェックを入れる


画像やファイルをアップロードする前・保存する前に、独自のチェックを挟みます。ファイルサイズの制限、命名規則の確認、外部システムへの問い合わせなどに使えます。

対応バージョン: Ver. 3.2.33 以降

実験的機能

この機能は Ver. 3.2 の間は実験的機能として提供し、Ver. 3.3 で正式に提供する予定です。

  • 変わりうる範囲: イベント名と、イベントが受け取る値の構造は、マイナーバージョンアップで変更される可能性があります。
  • 変わらない範囲: 従来の DOM イベント(acms.media-updated など)と ACMS.addListener は、今後も動作します。
  • 公開 API の線引き: このページに掲載しているイベントを公開 API として扱います。掲載外のものも利用できますが、告知なく変更されることがあります。
  • サポート対象外: 管理画面に追加した独自の JavaScript・CSS は、バージョンアップ後の動作を保証しません。これらを原因とする不具合は、サポートの対象外です。

基本の形

操作の直前に呼ばれるイベント(.before で終わるもの)のハンドラは、(payload, gate) の2つの引数を受け取ります。

引数内容
payload操作の対象になる値(アップロードするファイル、保存する内容など)。直接書き換えられます
gate操作を中止するための gate.cancel() を持つオブジェクト

ハンドラでできることは次の4つです。

やりたいこと書き方
何もしない(見るだけ)何もしない
操作を中止するgate.cancel() または gate.cancel('理由') を呼ぶ
値を書き換えるpayload のプロパティを書き換える
非同期の処理を待たせるasync 関数にする

確認ダイアログを出す

ACMS.adminReady(() => {
  ACMS.plugins.register('acme-media-rules', {
    setup(ctx) {
      ctx.events.on('media.upload.before', async (payload, gate) => {
        const ok = await ACMS.Library.dialog.confirm(`${payload.files.length} 件をアップロードします。よろしいですか?`);
        if (!ok) {
          gate.cancel();
        }
      });
    },
  });
});
  • gate.cancel() を呼ぶとアップロードされません。
  • ハンドラを async にすると、a-blog cms はその処理が終わるまでアップロードを待ちます。

理由を表示して中止する

ACMS.adminReady(() => {
  ACMS.plugins.register('acme-media-rules', {
    setup(ctx) {
      ctx.events.on('media.upload.before', (payload, gate) => {
        const tooLarge = payload.files.filter((file) => file.size > 5_000_000);
        if (tooLarge.length > 0) {
          gate.cancel(`5MB を超えるファイルはアップロードできません: ${tooLarge[0].name}`);
        }
      });
    },
  });
});

gate.cancel('理由') のように理由を渡すと、その文字列がそのまま利用者に表示されます。理由を伝えたい場合は、理由つきで呼んでください。理由を渡さない gate.cancel() は、何も表示せずに中止します。

チェックを通す場合は何もしなくてよいです(そのまま処理が続きます)。

gate.cancel() を呼ぶと、そのイベントの残りのハンドラは実行されません。

一部のファイルだけ除外する

ACMS.adminReady(() => {
  ACMS.plugins.register('acme-media-rules', {
    setup(ctx) {
      ctx.events.on('media.upload.before', (payload) => {
        payload.files = payload.files.filter((file) => file.type !== 'image/gif');
      });
    },
  });
});

payload を書き換えると、その内容が次のハンドラと、実際の処理に渡ります。

アップロードでは「除外」だけができます

media.upload.before では、すでに選択されているファイルを取り除くことはできますが、新しいファイルに差し替えることはできません(圧縮したファイルに置き換える、といった使い方はできません)。差し替えたい場合は、アップロードを中止して独自の処理でアップロードしてください。

保存内容を書き換える

メディアの詳細画面で保存する直前に、送信内容を書き換えられます。

ACMS.adminReady(() => {
  ACMS.plugins.register('acme-media-rules', {
    setup(ctx) {
      ctx.events.on('media.update.before', (payload) => {
        // field_3 が alt テキスト
        if (!payload.formData.get('field_3')) {
          payload.formData.set('field_3', payload.item.media_title);
        }
      });
    },
  });
});

payload.formData は保存される内容そのものです。値を追加・変更すると、その内容で保存されます。メディアの項目名は、field_1 がキャプション、field_3 が alt テキストです。

alt テキストを必須にしたい場合は、中止を使います。

ACMS.adminReady(() => {
  ACMS.plugins.register('acme-media-rules', {
    setup(ctx) {
      ctx.events.on('media.update.before', (payload, gate) => {
        if (payload.item.media_type === 'image' && !payload.formData.get('field_3')) {
          gate.cancel('alt テキストを入力してください');
        }
      });
    },
  });
});

alt テキストの入力欄が表示されない設定のとき

alt テキストの入力欄は、設定によっては詳細画面に表示されません。入力欄が見えない状態で alt を必須にすると、利用者が保存できなくなります。

「別名で保存」には、media.update-as-new.before が別に用意されています。受け取る値は media.update.before と同じです。

外部システムに問い合わせる

ACMS.adminReady(() => {
  ACMS.plugins.register('acme-media-rules', {
    setup(ctx) {
      ctx.events.on('media.update.before', async (payload, gate) => {
        const response = await fetch('/api/acme/validate-media/', {
          method: 'POST',
          body: payload.formData,
        });
        const result = await response.json();
        if (!result.ok) {
          gate.cancel(result.message);
        }
      });
    },
  });
});

/api/acme/validate-media/ は、検証を行う自前のエンドポイントの例です。非同期のチェックが終わるまで保存は待たされます。ただしユーザーは待たされている状態になるため、時間のかかる処理は避けてください。ハンドラが例外を投げた場合も、操作は中止されます。

アップロード後に処理する

完了後の通知は .success のイベントで受け取ります。こちらは中止できません。

ACMS.adminReady(() => {
  ACMS.plugins.register('acme-media-rules', {
    setup(ctx) {
      ctx.events.on('media.upload.success', (payload) => {
        console.log(payload.items); // 登録されたメディア
      });
    },
  });
});

削除を止める

ACMS.adminReady(() => {
  ACMS.plugins.register('acme-media-rules', {
    setup(ctx) {
      ctx.events.on('media.delete.before', (payload, gate) => {
        if (payload.mediaIds.length > 10) {
          gate.cancel('一度に削除できるのは 10 件までです');
        }
      });
    },
  });
});

削除では対象の絞り込みはできません。payload.mediaIds を書き換えても、実際に削除される対象は変わりません。一部だけ除外したい場合は、全体を中止したうえで、必要な操作を利用者に案内してください。

どの画面に効くか

メディア関連のイベントは、メディア選択を使うすべての画面で発火します。メディア管理の画面だけでなく、カスタムフィールド・ブロックエディターの画像/ファイル・リッチエディター・ユニットなどからのアップロードにも同じチェックが効きます。

同じプラグイン名を使う場合

このページの例は、どれも同じプラグイン名(acme-media-rules)で書いています。複数の例を1つのファイルで試す場合は、ACMS.plugins.register() を1回にまとめ、setup(ctx) の中に ctx.events.on() を並べてください。同じ名前で2回登録するとエラーになります。

関連ページ

変更履歴

バージョン変更内容
Ver. 3.2新規追加(実験的機能)