ユーザが画像ファイルをアップロードするWebアプリをつくる feat. AWS
要件
256x256 の画像ファイル (jpg or png) をWebアプリからユーザにアップロードさせたい
ブラウザから直接S3にアップロードする案
S3の Presigned Urlという仕組みを使うとユーザにオブジェクトを指定してアップロードさせるためのURLを発行できる ファイルサイズなどは制限できない?
いや、できそう?
ファイルサイズぐらいなら指定できそうだが、こまかいバリデーションなどはできない
LambdaからS3にアップロードする案
API GatewayのバイナリメディアタイプでファイルをLambdaに送る案
既存のAPIと別途API Gatewayをつくる必要がでてくる
画像をBase64エンコードしてJSONに入れちゃう案
こっちなら他の文字列と同じように扱える
Lambda同期呼び出しでのペイロードは6MBまで
API Gatewayはペイロード10MBまで
今回の要件の範囲内であればこれで事足りそう
Lambdaでファイル(ファイルサイズ、画像サイズ、拡張子など)をチェックしてS3にアップロード
プロトタイプ
code: my-server.js
var http = require('http');
http.createServer(function(req, res) {
req.on('data', function(chunk) {data += chunk})
.on('end', function() {
console.log(data);
res.writeHead(200);
res.end();
})
}).listen(3000);
code: upload-image.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Upload image</title>
<script>
let base64Data;
function previewFile() {
const preview = document.getElementById('preview-image')
const file = document.getElementById('preview-input').files0; const reader = new FileReader();
reader.addEventListener("load", function () {
// convert image file to base64 string
preview.src = reader.result;
base64Data = reader.result;
console.log({ base64Data });
}, false);
if (file) {
reader.readAsDataURL(file);
}
}
function submitImage() {
const xhr = new XMLHttpRequest();
xhr.send(JSON.stringify({ base64Data }));
xhr.onload = function() {
alert(Loaded: ${xhr.status} ${xhr.response});
};
xhr.onerror = function() {
alert(Network Error);
};
}
</script>
</head>
<body>
<div>Upload image</div>
<br>
<input id="preview-input" type="file" onchange="previewFile()"><br>
<br>
<img id="preview-image" src="" height="200" alt="Image preview...">
<br>
<br>
<button id="submit-image" onclick="submitImage()">送信</button>
</body>
</html>
$ node my-server.js
$ http-server
→ちゃんとbase64エンコードされたものが送れてそう