→ 外部URLの画像をimgタグ内で直接指定することはできません。マネジメントAPI等を利用し、microCMSにアップロードした画像のURLを利用する方法をご案内します。
WRITE APIでリッチエディタにコンテンツを登録する際、imgタグのsrc属性に指定できる値はmicroCMSのドメインのURL(https://images.microcms-assets.io/~)のみとなります。
ですので、直接外部のURLの画像を指定することはできません。
画像 - リッチエディタのWRITE API|microCMSドキュメント
代替手段
マネジメントAPIを用いて、外部URLの画像を一度microCMSにアップロードし、取得したURLを用いて置換するなどの方法で対応することは可能です。
一例として、特定のHTMLファイル(imgタグで外部のURLのメディアを読み込んでいる)を読み込み、その内容をmicroCMSの任意のAPIで用意しているリッチエディタにアップロードする方法を考えます。
具体的な処理の流れは以下のとおりです。
- 特定のHTMLファイルを読み込む(今回は同階層にある sample.html を対象にしています)
- 1で読み込んだHTMLファイル内で使われている画像を洗い出す
- 2で洗い出した画像のURLを元に、マネジメントAPIの画像アップロードAPIでアップロードする
- 3のレスポンスとして得られるmicroCMSドメインのURLを用いて、1のHTMLファイルの画像タグの内容を書き換える
- コンテンツAPIでコンテンツをアップロードする
なお、手順1で読み込むHTMLファイル(body要素以下)は以下のようなものを想定しています。このHTMLにおける、article要素の中身をリッチエディタのコンテンツに登録するイメージです。
<body>
<article>
<p>
<img src="https://placehold.jp/400x400.png" alt="サンプル画像1">
</p>
<p>
<img src="https://placehold.jp/500x500.png" alt="サンプル画像2">
</p>
<p>
<img src="https://placehold.jp/600x600.png" alt="サンプル画像3">
</p>
</article>
</body>
上記の前提を踏まえ、処理を実装したコードの例(Node.js)を示します。
import fs from "fs/promises";
import * as cheerio from 'cheerio';
import { createClient, createManagementClient } from 'microcms-js-sdk';
// クライアント(コンテンツAPI)
const contentClient = createClient({
serviceDomain: 'some-domain',
apiKey: 'some-api-key',
});
// クライアント(マネジメントAPI)
const managementClient = createManagementClient({
serviceDomain: 'some-domain',
apiKey: 'some-api-key',
});
// 画像をアップロードし、新旧それぞれのURLを返却する関数
const uploadImage = async (imgSrc) => {
try {
const { url } = await managementClient.uploadMedia({ data: imgSrc });
return { oldUrl: imgSrc, newUrl: url };
} catch (err) {
console.error(`Upload failed for ${imgSrc}:`, err);
}
};
// ディレイを実行する関数
const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
// メイン処理
const main = async () => {
try {
// 手順1: HTMLファイルを読み込む
const data = await fs.readFile('sample.html', 'utf8');
const $ = cheerio.load(data);
// 手順2: HTMLファイルのbodyタグ内で使われている画像を洗い出す
const imgTags = $('body img');
// 手順3: imgタグのURLをマネジメントAPIでアップロードする
// マネジメントAPIのレートリミットに抵触しないよう、直列でリクエストし、リクエスト間では1秒ディレイさせる
const uploadResults = [];
for (let i = 0; i < imgTags.length; i++) {
const imgSrc = $(imgTags[i]).attr('src');
if (imgSrc) {
const result = await uploadImage(imgSrc);
if (result) uploadResults.push(result);
await delay(1000);
}
}
// 手順4: 元のURLからmicroCMSのドメインのURLに置換
uploadResults.forEach(({ oldUrl, newUrl }) => {
$(`img[src="${oldUrl}"]`).attr('src', newUrl);
});
// articleタグの中身を抽出(WRITE APIに対応しているタグのみを送信するため)
const updatedHtml = $('body > article').html().replace(/"/g, "'");
// 手順5: コンテンツAPIでアップロードする
const response = await contentClient.create({
endpoint: 'some-endpoint',
content: { body: updatedHtml }, // "body"フィールドはリッチエディタ
});
console.log(`Content created with ID: ${response.id}`);
} catch (err) {
console.error('Error:', err);
}
};
main();
なお上記のコードは、例としてシンプルにするために、以下のような前提で記述しています。
- 同階層にある、単一のhtmlファイルに対する処理としています
- htmlファイル内のimgタグでは絶対パスのURLが指定されていることを想定しています。相対パスが指定される可能性がある場合は、ドメイン部分を補完するなどを考慮して実装してください
- 画像の重複は考慮していません
- HTML内で同じ画像が使われている場合も、別の画像として扱われます