Movable Type の Data APIを利用してアプリ開発などを行う場合、画像をアップロードしたい、という場面もあると思います。
Data APIから画像をアップロードする方法について、サンプルコードを書いてみました。
やること
- Movable Type の Data API を使って、画像をアップロード。Movable Type に登録する。
- JavaScript で実装する
- jQuery、Movable Type のJavaScript SDK を利用する。
検証環境
- Movable Type 6.3.3
- Google Crhome, Microsoft Edge
画像をアップロードする
以下のような流れで考えてみました。
- JavaScript SDKで認証を行う
- html5のFile API で画像のサムネイル表示
- 画像をアップロードしたいパスを入力
- アップロードボタンを押すことで、画像をサーバー上にアップロードし、MTのアイテムとして登録する
認証およびMTへの登録は Data API、入力値の反映などはjQueryで行います。
mt-image-upload.html
<!DOCTYPE html>
<html lang="ja">
<head>
<title>画像をMTに登録するサンプル</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
<script src="<$MTStaticWebPath$>data-api/v3/js/mt-data-api.js"></script>
</head>
<body>
<div class="container" id="container">
<h2>画像をMTへ登録するサンプル</h2>
<div id="message"></div>
<div id="content" style="display: none;">
<p><input type="file" name="upload" id="fileToUpload"></p>
<p>アップロードパス</p>
<p><input type="text" name="path" id="path">
<p><button id="uploadFile">MTへアップロード</button></p>
</div>
</div>
<script>
// Movable Type Data API のインスタンス生成
const api = new MT.DataAPI({
baseUrl: "<$MTCGIPath$><$MTDataAPIScript$>",
clientId: "image-upload"
});
// MTのブログIDを変数 siteId に格納
const siteId = <$MTBlogID$>;
// メッセージ表示のために使う変数 [html] を定義
let html = '';
$(function() {
// MTにサインインしているかどうか、トークンを確認する。
// トークンがない場合、サインインを促す。存在した場合、hiddenで隠されている登録用フォームを表示する
if (!api.getTokenData()) {
let html = `
<p>画像を登録するためにはサインインしてください。</p>
<p><input type="button" id="signin" class="btn btn-primary btn-lg" value="サインイン"></p>
`
$("#message").html(html);
} else {
$("#content").show();
}
// サインインをクリックしたら、SDKの関数 [getAuthorizationUrl] を実行して、サインインを行う
$("#signin").on("click", function() {
location.href = api.getAuthorizationUrl(location.href);
});
// アップロードするファイルを選択
$('input[type=file]').after('<p><span id="image"></span></p>');
$('input[type=file]').change(function() {
const file = $(this).prop('files')[0];
// 画像以外は処理を停止
if (!file.type.match('image.*')) {
$(this).val('');
$('span').html('');
return;
}
const reader = new FileReader();
reader.onload = function() {
const img_src = $('<img height=\"300\">').attr('src', reader.result);
$('span').html(img_src);
}
reader.readAsDataURL(file);
});
// 登録ボタンをクリックしたら、アップロード用の関数[upload]を実行する。
$("#uploadFile").on("click", function() {
upload();
});
// 画像をアップロードしてMTに登録する。エラーになったら、レスポンスデータからエラーメッセージを表示。それ以外は成功メッセージを表示
function upload() {
const data = {
site_id: siteId,
path: $("#path").val(),
file: $("#fileToUpload")[0].files[0],
autoRenameIfExists: true,
normalizeOrientation: true,
};
api.uploadAsset(data, function(response) {
if (response.error) {
alert(response.error.message);
return;
}
alert("画像をアップロードしました。");
return;
});
}
});
</script>
</html>
画像をアップロードするときに、画像の説明やタグも合わせて登録する
画像の情報に説明やタグなどを加えたい場合は、以下のような流れになります。
- JavaScript SDKで認証を行う
- html5のFile API で画像のサムネイル表示
- 画像をアップロードしたいパスを入力
- アップロードボタンを押すことで、画像をサーバー上にアップロードし、MTのアイテムとして登録する
- アップロード後に取得したレスポンスデータから、登録された画像のアイテムIDを取得する
- [PUT]メソッドで、アイテムIDの情報に、説明とタグを加えてupdateする
4から5にデータを渡すためには、非同期通信の処理を待って次の処理へ渡す必要があります。今回はJavaScriptのPromise メソッドを使って、アップロードに対するレスポンスデータを引き渡しました。
Promise に関しては、こちらの記事 をご参照ください。
タグの情報は、カンマ区切りで入力します。カンマごとに語句を分割して配列[tags]に格納後、Data API に渡しています。
アイテムをアップデートするためのエンドポイント update を、JavaScript SDKで叩きます。
mt-upload-image-1.html
<!DOCTYPE html>
<html lang="ja">
<head>
<title>タグや説明を付加した画像をMTに登録するサンプル</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
<script src="<$MTStaticWebPath$>data-api/v3/js/mt-data-api.js"></script>
</head>
<body>
<div class="container" id="container">
<h2>タグや説明を付加した画像をMTへ登録するサンプル</h2>
<div id="message"></div>
<div id="content" style="display: none;">
<p><input type="file" name="upload" id="fileToUpload"></p>
<p>アップロードパス</p>
<p><input type="text" name="path" id="path">
<p>画像の説明</p>
<p><input type="text" name="desc" id="desc">
<p>画像のタグ</p>
<p><input type="text" name="tags" id="tags">
<p><button id="uploadFile">MTへアップロード</button></p>
</div>
</div>
<script>
// Movable Type Data API のインスタンス生成
const api = new MT.DataAPI({
baseUrl: "<$MTCGIPath$><$MTDataAPIScript$>",
clientId: "image-upload-1"
});
// MTのブログIDを変数 siteId に格納
const siteId = <$MTBlogID$>;
// メッセージ表示のために使う変数 [html] を定義
let html = '';
$(function() {
// MTにサインインしているかどうか、トークンを確認する。
// トークンがない場合、サインインを促す。存在した場合、hiddenで隠されている登録用フォームを表示する
if (!api.getTokenData()) {
let html = `
<p>画像を登録するためにはサインインしてください。</p>
<p><input type="button" id="signin" class="btn btn-primary btn-lg" value="サインイン"></p>
`
$("#message").html(html);
} else {
$("#content").show();
}
// サインインをクリックしたら、SDKの関数 [getAuthorizationUrl] を実行して、サインインを行う
$("#signin").on("click", function() {
location.href = api.getAuthorizationUrl(location.href);
});
// アップロードするファイルを選択
$('input[type=file]').after('<p><span id="image"></span></p>');
$('input[type=file]').change(function() {
const file = $(this).prop('files')[0];
// 画像以外は処理を停止
if (!file.type.match('image.*')) {
$(this).val('');
$('span').html('');
return;
}
const reader = new FileReader();
reader.onload = function() {
const img_src = $('<img height="300">').attr('src', reader.result);
$('span').html(img_src);
}
reader.readAsDataURL(file);
});
// 登録ボタンをクリックしたら、関数[upload]を実行。非同期通信のレスポンスが返ってきたら、次の関数[update]に値を引き渡し、タグと説明データを加える。
$("#uploadFile").on("click", function() {
upload().then(function(response) {
update(response);
});
});
// 画像をアップロードしてMTに登録し、レスポンスデータを Promise で渡す
function upload() {
return new Promise((resolve, reject) => {
const data = {
site_id: siteId,
path: $("#path").val(),
file: $("#fileToUpload")[0].files[0],
autoRenameIfExists: true,
normalizeOrientation: true,
};
api.uploadAsset(data, function(response) {
if (response.error) {
alert(response.error.message);
reject;
}
resolve(response);
});
});
}
// 関数 upload() から返ってきたレスポンスデータを元に、タグと説明のデータを追加してアップデートする
function update(response) {
const assetId = response.id;
const tag = $("#tags").val();
const tags = tag.split(',');
const extData = {
description: $("#desc").val(),
tags: tags,
};
api.updateAsset(siteId, assetId, extData, function(result) {
if (result.error) {
alert("アイテムの情報をアップデート中にエラーが発生しました。");
return;
}
alert("画像をアップロードしました。");
return;
});
}
});
</script>
</html>
出力したhtmlで画像を登録する画面。
登録後の画像。タグや説明が付加されています。