type=”file”のinputタグをJSで操作する方法
こんにちは、デザイン戦略部の田中です。
今回は私が最近担当した案件で苦労した、type="file"のinputの値と全く同じ形式のデータを0から作る方法と、データをフォームでアップロードする方法各種について書いていこうと思います!
input type="file"について
基本的にinput type="file"の値というのは、type="text"などのほかのinput要素と違い変更したり設定したりすることはできません。
もしこれができてしまうと悪意のあるコードなどによってファイルを勝手に送ったり送られたりできてしまう可能性があるため、セキュリティ的観点からそういった仕様になっているそうです。
参考:https://www.hos.co.jp/blog/20180129/
要件について
今回の案件で実装したかった要件では、既存のinputタグと既存のバックエンドプログラムを使ってcanvasから生成した画像を新たなサムネイル画像として更新するというものです。
弊社ではバックエンドを作ったり修正したりするのは、私のいるデザイン戦略部ではなく技術戦略部という別の部署が担当する為、今回はできればその辺の中身はいじらずデザイン戦略部のみで実装したいという状況でした。
今回うまくいかなかったやり方
私にはバックエンドのソースを見て仕様を理解できるスキルがないため、何らかの画像的なデータをinputに入れ込めば送れるようになるものかなと思っていました。。。。
その状態で試してみたのが以下などです。
試してみたこと
・DataURLをそのまま代入
・blobデータをそのまま代入
・ArrayBufferデータをそのまま代入
・blobデータをフォームデータにappendしてそれを置き換え
・ArrayBufferデータをフォームデータにappendしてそれを置き換え
そのほかにはURL.createObjectURL(blob)を使ってできたURLを入れてみたりもしましたがこちらはページ間のやり取りでは使わないようですね。
などなどを試してみたのですが、送信が成功することはありませんでした。。。
このへんで自力では無理そうと判断し技術戦略部のメンバーにうまくできない旨相談したところ、既存のinputに入るfile情報とデータの形式を全く同じにするようアドバイスされました。
最終的にできたやり方
最初検索し始めて、え!type="file"のinputの値は作ったり操作できないって書いてるし、無理じゃん!!と思ったのですが、あきらめず検索し続けて一つだけできる方法があると言っているサイトを見つけました。
DataTransferというオブジェクトを使う方法です。
DataTransferとは?
DataTransfer オブジェクトは、ドラッグ&ドロップ操作中にドラッグされているデータを保持するために使用されます。これは、1つ以上のデータ項目を保持することができ、それぞれが 1 つ以上のデータ型を持ちます。
参照:https://developer.mozilla.org/ja/docs/Web/API/DataTransfer
具体的には新規作成したDataTransferのitemsに、canvasから生成したblobをaddして、できたFileListをinput type="file"のfilesに代入する方法になります。
以下が実際に書いたコードです。
cnvs_trimed.toBlob(function(blob) {
const csvFile = new File([blob], 'trimedfileupload.png', {type: "image/png"});
const dt = new DataTransfer();
dt.items.add(csvFile);
document.getElementsByName("trimedData")[0].files = dt.files;
});
参考にさせていただいたサイト:https://cpoint-lab.co.jp/article/202203/22236/
最初の項で変更したり設定したりできないと言っていたinput type="file"の値ですが、DataTransferを使えばこのように意外と簡単に実現することができます!
DataTransferは元々ドラッグ&ドロップ用のオブジェクトですので、こちらを使えばライブラリなどを使わずにドロップエリアを作ったりもできるみたいですね!
参考:https://blog.ver001.com/javascript-datatransfer/
現状弊社サイトにあるドロップエリアはjQueryとDropzone.jsを使っているものが多かったのですが、vue.jsなどに移行していく際こちらを使っていくとよさそうだなと思いました。
最後に
私が参考にさせていただいたページ以外にも、DataTransferで検索するといくつかこの方法について詳しく説明しているページを見つけました。(0からの検索って難しい。。。)
有名なMDN web docsにもこれと似たことをやってるページがありますね!↓
https://developer.mozilla.org/ja/docs/Web/API/File_API/Using_files_from_web_applications
ビジュアル先行のサイトや直感的な操作のできるUIが増えている中で、実装に必要な場面も増えるオブジェクトかなと思います。ぜひ検索して理解を深め活用してみてくださいね!
さて、ラクーングループでは、一緒に働く仲間を絶賛大募集中です!
今回の案件の私のように未熟な状態でも挑戦させてもらえて、成長できる職場です。
もしご興味を持っていただけましたら、こちらからエントリーお待ちしています!