Canvasのimageをfileにして送信

noteを始めてから13日連続で更新していたのですが、日付が変わってしまって連続更新が途絶えてしまって残念です…笑
連続で更新すると、noteが「すばらしいです!」って投稿するときに褒めてくれるのに…。

さて、新機能についての説明です。
動画のスクショをcanvasに貼り付けて、線を描き込んだあと、それをコメントに載せてサーバーに送信します。

ここでやっていることは、

1. canvas.toDataURL()でbase64を得て、それをsrcにセットしたimgタグでサムネイルをコメントフォームに表示

2. そのbase64をもとにBlobを生成、コメント用のスクショとして取っておく(ほかのスクショがコメントに添付されない限りずっと保存)

3. コメントがサブミットされるタイミングで、撮っておいたコメント用のスクショBlobを、formdataのfileに追加する

って感じですね。

1. のサムネ表示は、もともとinput[type="file"]のchangeで発火するイベントのよるものでしたが、こういう例外が発生してきてちょっと嫌ですね笑
2. のbase64 ⇒ BlobはBase64toBlobみたいな関数がネット上に転がっています。
3. のBlobをコメントに載せるところですが、HTMLのinput要素にファイル(具体的にはinput[type="file"]のvalueに""以外)を設定することが出来ません。
昨日の記事にも書きましたが、C:/password.txtを勝手にセットする、みたいなヤバイことが出来てしまうからです。
そこで、

//POSTするデータを取り出す
let fd = new FormData($('#postform').get(0))
//元のセットしてあったファイルを削除
fd.delete("file")
//スクショを載せる
fd.append("file", screenshot_file, screenshot_file.name)

みたいなコードで、直接POSTするデータに追加します。
もとのinput[type="file"]はいじってないので、Ajaxでこのformdataを送信することになります。
fd.appendの第三引数で名前指定できるんですね、知らなかった。
勝手にBlobのnameがセットされると思っていました。
(formdata周り : https://developer.mozilla.org/ja/docs/Web/Guide/Using_FormData_Objects)

ちなみに、スクショエディタを閉じるときに、コメントに添付していないスクショが破棄される場合は、「このスクリーンショットは破棄されます、よろしいですか?」とconfirmが出ますが、これは、canvasのimageが厳密に変化したかは比べていません。
imageの中身そのものを比べるのは面倒そうだったので、ファイルサイズを比べることで同一判定をしています。
千回に一回くらい、違うimageなのにファイルサイズが同じでconfirmが出ない可能性がありますが、その確率の低さとconfirmでしかないという二点で、ファイルサイズで同一判定するのは正解だったと思います。

とまぁコメントにcanvasのimageを載せるのはこんな感じで実装しました。
また明日!


今日もお読みくださりありがとうございます。
ほぼ毎日、アプリ開発や事業に関する日記を書いておりますので是非またお読みになってください!

この記事が気に入ったらサポートをしてみませんか?