概要
バイナリファイルを 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 件のコメント:
コメントを投稿