Open4

Google Chart APIが廃止したみたいなのでNestJSを使って互換性のあるAPIを自作する

tsururintsururin

QRコードの動的生成にGoogle Chart APIを使用していたが、2024年4月頃から404を返すようになった。以前から廃止と言われていたけど使えていたので使っていたがついに使えなくなったようだ。

tsururintsururin

代替サービスに「QR code API」というのがあったが、生成される画像がやや違った。今回はGoogle Chart APIで出てくる画像と、全く同じ画像がほしかったので自作してみる。

tsururintsururin
import { Storage } from '@google-cloud/storage';
import { Controller, Get, Query, Res } from '@nestjs/common';
import { Response } from 'express';
import * as QRCode from 'qrcode';
import { finished } from 'stream/promises';

export class Options {
	text: string = '';
	size: number = 512;
}

@Controller(`tool`)
export class QrCodeGenerator {
	private readonly storage = new Storage();

	@Get('qrcode')
	public async action(@Query() options: Options, @Res() res: Response): Promise<void> {
		// バリデーション
		if (!options.text) {
			throw new Error('textを指定してください。');
		}

		const fileName = `qrcode/${encodeURIComponent(options.text)}_${options.size}.png`;

		// GCSにあるか
		const bucket = this.storage.bucket(process.env.GCLOUD_STORAGE_BUCKET_FOR_QRCODE);
		const blob = bucket.file(fileName);
		const exists = await blob.exists();

		// なければ作成
		if (!exists[0]) {
			console.log(`作成します。text: ${options.text}`);
			try {
				const blobStream = blob.createWriteStream();
				// Google Chart APIに合わせる
				await QRCode.toFileStream(blobStream, options.text, {
					width: options.size,
					margin: 5,
					errorCorrectionLevel: 'L',
				});
				await finished(blobStream);
			} catch (e) {
				console.error(e);
				throw new Error('失敗しました。');
			}
		}

		blob.createReadStream().pipe(res);
	}
}
tsururintsururin

これで全く同じ画像ができた。初めてのアクセスの時に作成してキャッシュしている。