フロントエンドで画像を縮小する

過去に沖縄メンバーによる同様の記事がありますが、今回は外部モジュールは使わず、Base64でエンコードしたテキストデータを扱う方法になります。

<input name=”up_file_s” type=”hidden”> に格納したかったので。

縮小した画像は、$(“img[id=up_file_preview]”) に描画しています。

画像は、長辺が600画素となるようにしています。

コードの断片になりますが、どなたかの一助になりましたら。

ロードした画像を縮小してBase64でinputに保持

var reader = new FileReader();

{{-- 画像が読み込まれた時の動作を記述 --}}
reader.onload = function (e) {

	{{-- 画像を縮小してhiddenに保存 --}}
	var img = new Image();
	img.onload = function() {
		var canvas = document.createElement('canvas');
		var ctx = canvas.getContext('2d');
		var maxWidth = 600;
		var maxHeight = 600;
		var width = img.width;
		var height = img.height;

		if (width > height) {
			if (width > maxWidth) {
				height *= maxWidth / width;
				width = maxWidth;
			}
		} else {
			if (height > maxHeight) {
				width *= maxHeight / height;
				height = maxHeight;
			}
		}

		canvas.width = width;
		canvas.height = height;

		ctx.drawImage(img, 0, 0, width, height);
		const dataURL = canvas.toDataURL('image/jpeg');
		$("input[name='up_file_s']").val(dataURL);
	};
	img.src = e.currentTarget.result;

	$("img[id=up_file_preview]").attr('src', e.currentTarget.result);
	$("img[id=up_file_preview]").show();
};

reader.readAsDataURL(e.currentTarget.files[0]);

カスタムバリデーションルール

長辺が600画素以上のデータを送信したくなかったので。

Base64でエンコードされている画像の長辺が指定値以下かどうか?

// 画像の長辺の縦横画素数が指定値以下か?
Validator::extend('base64ImageMaxLongBoundary', function ($attribute, $value, $parameters, $validator) {
	$decodedImage = base64_decode(substr($value, strpos($value, ',') + 1));
	$imageInfo = getimagesizefromstring($decodedImage);
	$width = $imageInfo[0];
	$height = $imageInfo[1];

	return ($width <= $parameters[0] && $height <= $parameters[0]);
});

rule

'up_file_s' => 'nullable|base64ImageMaxLongBoundary:600',

受け側(apply)でちゃんとBase64の画像かどうかチェック

$imgFileに受信した画像データが入っているとして

// 受信画像はBase64エンコードされたテキストに限定
if (base64_encode(base64_decode($imgFile, true)) === $imgFile) {
	logger()->warning("Uploaded image is not Base64 encoded.");
	return;
};

受け側(apply)でBase64をデコードして画像の長辺をチェック

$imgBase64 = preg_replace('/^data:image.*base64,/', '', $imgFile);
$imgBase64 = str_replace(' ', '+', $imgBase64);


// 画像サイズを確認
$binary = base64_decode(explode(',', $imgFile)[1]);
$imageSize = getimagesizefromstring($binary);
if ($imageSize[0] > 600 || $imageSize[1] > 600) {
	logger()->warning("Uploaded image size is too large (long boundary > 600 pix)");
	return;
}

受け側(apply)でファイル保存できるように変換

$imgBase64 = preg_replace('/^data:image.*base64,/', '', $imgFile);
$imgBase64 = str_replace(' ', '+', $imgBase64);
$fileData = base64_decode($imgBase64);