2022年3月10日木曜日

jQuery でイメージファイルを base64 エンコードデータに変換する方法

jQuery でイメージファイルを base64 エンコードデータに変換する方法

概要

バイナリファイルを base64 エンコードファイルに変換する方法を紹介します
サーバサイドでデータベースにテキストデータとして保存する場合に役に立ちます

FileReader API の readAsDataURL というメソッドを使います

環境

  • macOS 11.6.4
  • Ruby 3.0.3p157
  • sinatra 2.2.0

サーバ側実装

  • bundle init
  • vim Gemfile
gem "sinatra"
gem "thin"
  • bundle install
  • mkdir views public upload
  • vim app.rb
# coding: utf-8
require 'sinatra'

class TestUpload < Sinatra::Base
  get '/' do
    erb :index
  end

  post '/upload' do
    base64str = params['base64str']
    content_type :json, :charset => 'utf-8'
    {"result": base64str}.to_json
  end
end

サーバ側はデータをフォームデータとして取得することを想定しています
今回は受け取ったデータの保存などはせずそのままクライアントに返却しています

クライアント側実装

  • vim views/index.erb
<!DOCTYPE HTML>
<html>
  <head>
  <meta charset="utf-8">
  <title>Upload Test</title>
  </head>
<body>
<input id="upload_file" type="file" name="file">
<button id="upload" type="button">Upload</button>
<div id="result"></div>
<img id="uploaded_img" src=""></img>
<script src="https://code.jquery.com/jquery-3.6.0.min.js" integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous"></script>
<script>
$(function () {
  $('#upload').click(function() {
    let file = $('#upload_file').prop('files')[0];
    // 3MiB
    let max = 3 * 1024 * 1024
    if (file.size > max) {
      $('#result').text("File size must be 3mib or less.")
    } else {
      let reader = new FileReader();
      reader.addEventListener("load", function (){
	let fd = new FormData();
        fd.append("base64str", reader.result);
        $.ajax({
          url:'/upload',
          type:'post',
          data: fd,
          processData: false,
          contentType: false,
          cache: false,
        }).done(function (data) {
          $('#result').text("uploaded.")
	  $('#uploaded_img').attr('src', data.result)
        }).fail(function() {
          $('#result').text("upload failed.")
        });
      }, false);
      if (file) {
        reader.readAsDataURL(file);
      }
    }
  });
});
</script>
</body> 
</html>

FileReader を生成し readAsDataURL の引数にファイルオブジェクトを渡します
そして FileReader オブジェクトに対して load イベントリスナーを設定します
すると base64 化が完了したときに load イベントがコールされその中で reader.result のようにすることで base64 化された画像の文字列情報が取得できます

送信するのはフォームデータにしています
理由はいくつかありますが JSON にしてしまうと base64 化された文字列をサーバ側でパースする際にパースエラーが発生するためフォームデータにしています

最後に

サーバ側にファイルデータを送信する際にバイナリをそのまま送信してもいいのですがクライアント側で base64 にしてあげるとサーバ側で頑張る必要が少なくなります

ちなみに ruby でも Base64.strict_encode64 とするだけで base64 化できるのでできるのはサーバサイドでもクライアントサイドでもどちらでもできます

参考サイト

0 件のコメント:

コメントを投稿