Fusic Tech Blog

Fusion of Society, IT and Culture

react-webcamで撮影した画像をJPEG変換に変換しS3へアップロードする
2022/01/31

react-webcamで撮影した画像をJPEG変換に変換しS3へアップロードする

岡嵜です。

PCのWebカメラを使って写真を撮影・アップロードするシステムをメンテナンスしていて、得られた知見を記事にします。

react-webcam

react-webcam とはReactで利用できるWebカメラのコンポーネントです。

あるシステムでは、Reactで作ったアプリケーションからWebカメラを利用した写真撮影を行っており、利用しています。

S3へのアップロード

撮影した画像をクラウドに送信する際、S3の署名付きURLを用いています。これにより複雑な認証処理を実装することなく簡単にS3へ画像をアップロードすることができます。

署名付きURLはサーバーサイド(今回はRuby on Rails)で発行し、Reactコンポーネントにpropsとして受け渡しています。図にまとめるとこういった構成です。

解決したかった課題

react-webcamの getScreenshot() というメソッドを使って写真撮影すると、返ってくるデータが base64エンコードされた文字列データ となります。

撮影した写真をJSON等に埋め込んで送信する場合には便利なのですが、画像として処理する場合には毎回base64デコードが必要となり不便です。

今回の構成だと、フロントエンドのReactアプリにて画像をJPEGに変換して送信することで、各種システムでのbase64デコード処理をSKIPしたいと考えました。

解決策

以下のようにbase64エンコードされた文字列データをデコードし、S3の署名付きURLに対してPOSTしました。

// 画像を撮影
const webcamRef = useRef<Webcam>(null);
const image = webcamRef?.current?.getScreenshot();

// base64デコード
const blob = atob(image.replace(/^.*,/, ''));
let buffer = new Uint8Array(blob.length);
for (let i = 0; i < blob.length; i++) {
    buffer[i] = blob.charCodeAt(i);
}

// S3へPOST
const res = await fetch(url, {
  method: 'PUT',
  headers: { accept: 'image/jpeg' },
  body: new File([buffer.buffer], 'image.jpeg', { type: 'image/jpeg' })
})

当初、S3へ画像をPOSTする際、bodyFormData にする必要があるのでは?と推測していましたがFileオブジェクトをそのままbodyにPOSTして問題ありませんでした。

まとめ

react-webcam は使いたいけど、base64データは扱いにくいな」と感じている方はぜひお試しください。

yuuu

yuuu

2018年の年明けに組込み畑からやってきた、2児の父 兼 Webエンジニアです。 mockmockの開発・運用を担当しており、組込みエンジニア時代の経験を活かしてデバイスをプログラミングしたり、簡易的なIoTシステムを作ったりしています。主な開発言語はRuby、時々Go。