発端
なでしこ3のweb版(wnako)は、ブラウザ上で動作するため、セキュリティ上ローカルPCのファイル操作はできません。コンソール版(cnako)をインストールする必要があります。
でも、ローカルPCのファイルを処理したいことは多々ありますよね~?
テキストや画像をブラウザ上で解析したり加工編集したりできるようにしたい❗️ とか?
15パズルを自分の好きな画像を使って遊ベルようにしたいんじゃー‼️ とかとか?
ユーザーが自分で選択したファイルなら、Javascript的には File API を使えば、これらのことが可能です。
なんでなでしこさんには実装されていないんだ😢
ワタクシどうしてもコレがやりたかったもので、自前でなでしこさんからFileReaderの機能を使うためのプラグインを作りました☆
これは当初個人的に使っていましたが、以前掲示板でこうゆうことは出来ないかという質問があったりしてなでしこ貯蔵庫に公開したりしましたが、今年また同様の質問があったりしてもしかして需要ある⁉️ となったので、ここに使い方を書き残しておくことにする。
プラグインを取り込む
なでしこ貯蔵庫にプラグインとして公開しています。
CC0で公開しており、使用も改変も自由です☆
使用するにはまず、プラグインを取り込む必要があります。
!「https://n3s.nadesi.com/plain/nadesiko3-FileReader.js」を取り込む。
ファイル選択
input[type='file']
要素のことです。
これに渡したファイルがファイルリストとしてfiles
プロパティに入り、プログラムから参照できるようになります。
ファイル選択作成
ファイル選択(input[type='file'])を作成しDOMオブジェクトを返します。
セキュリティ上、ユーザーが自分で選択したファイル以外は開けませんので、対応ブラウザであればファイル選択のUIが表示されます。
外観はブラウザごとの仕様によります。CSSでかっこよくしたり出来るらしいです。
ファイル選択の属性
-
multiple
複数選択を許可するかどうかを指定します。
winなら、shiftを押しながらずらっと選択したり、ctrlを押しながら、任意に選択したりできます。 -
accept
受け入れるファイルタイプを指定します。
固有ファイル型指定子をカンマ( , )で区切ったリストを記述します。
拡張子 | ドット(.) で始まる有効なファイル拡張子(.csv,.jpg,.mp3とか) |
MIMEタイプ | 有効なMIMEタイプ文字列で拡張子のないもの(text/htmlとか) |
image/* | 任意の画像ファイルを意味する |
audio/* | 任意の音声ファイルを意味する |
video/* | 任意の動画ファイルを意味する |
ファイル選択時
引数: ファイル選択で|ファイル選択の
ファイル選択UIで実際にファイルが選択された際に実行するイベントを設定します。
『対象』に、選択されたファイルリストが入ります。
一つしか選択していない場合でも、最初のファイルということで対象[0]
とする必要があります。
ファイルオブジェクトのプロパティ
name | ファイル名 | セキュリティ上のアレによりパスはつきません |
size | ファイルサイズ | バイト単位 |
type | ファイルタイプ | text/plainとかimage/jpegとかとか |
lastModified | 最終更新時刻 | UTC(1970/1/1)からの経過ミリ秒数 |
なでしこの日時変換
は、UTC(1970/1/1)からの 経過秒数 を日時に変換するヤツなので注意。
サンプル
!「https://n3s.nadesi.com/plain/nadesiko3-FileReader.js」を取り込む。
テスト=ファイル選択作成。
テストの「multiple」に、はいをDOM属性設定。#複数選択を許可
テストでファイル選択した時には、
対象を反復
対象["name"]を表示。
対象["type"]を表示。
対象["size"]&「バイト」を表示。
(対象["lastModified"]/1000)を日時変換して表示。
「----------」を表示。
ここまで。
ここまで。
ドラッグ&ドロップ
いちおうドラッグ&ドロップでも出来たらかっこ良くない? と思ってやってみたら、なんかコレが一番面倒くさかったです💧
ファイルドロップ時
引数: DOMに|DOMへ
DOMへファイルがドロップされた際に実行するイベントを設定します。
『対象』に、ドロップされたファイルリストが入ります。
一つしかドロップしていない場合でも、最初のファイルということで対象[0]
とする必要があります。
ドロップ禁止
引数: DOMに|DOMへ
DOMへのファイルドロップ操作を無効にします。
これは、目的のDOMにファイルをドラッグ&ドロップしようとしていて、うっかり途中で落っことしちゃったりすると、ブラウザ規定の動作でそのファイルが開かれてしまい、プログラムが中断させられてしまったりするのを防ぐために、
WINDOWへドロップ禁止。
とか、しておきます。
サンプル
!「https://n3s.nadesi.com/plain/nadesiko3-FileReader.js」を取込む。
WINDOWへドロップ禁止。
描画中キャンバスにファイルドロップした時には、
対象を反復
対象["name"]を表示。
対象["type"]を表示。
対象["size"]&「バイト」を表示。
(対象["lastModified"]/1000)を日時変換して表示。
「----------」を表示。
ここまで。
ここまで。
Tips
ファイル選択とドラッグ&ドロップの両方出来るようにした場合、ドラッグ&ドロップしてもファイル選択のほうは「ファイルが選択されていません。」のままであり、見た目アレ? って感じになります。
ファイルドロップ時
の対象
を、ファイル選択のfiles
に設定してやりましょう。
!「https://n3s.nadesi.com/plain/nadesiko3-FileReader.js」を取込む。
WINDOWへドロップ禁止。
テスト=ファイル選択作成。
描画中キャンバスにファイルドロップした時には、
テストの「files」に対象をDOM属性設定。
ここまで。
これで、連動して動作してる感が出ます♪
ファイルを開く
FileReader API で、実際にファイルを読み込みます。
開ける形式は、拡張子(MIMEタイプ)を見ているだけです。
拡張子と実際の中身が違っていた場合、開けず、エラーも出ず、です。
テキストファイル追加拡張子
初期値: csv|tsv|json|js|nako|nako3
パイプ(|)区切りでドット(.)無しの拡張子のリストを指定。
テキストは、text/*
しても、txtとhtmlくらいしか開かず、以前はcsvも開いた気がするけど開けなかった。text/csvからapplication/csvに変わってるっぽい?
他にも実態はプレーンテキストな開きたいものいろいろある気がしたので後からも指定出来るようにした変数。
テキストファイル開時
引数: 文字コードでファイルの|ファイルを
ファイル選択やドラッグ&ドロップで取得したファイルオブジェクトを指定して、テキストファイルを開いて文字列を返します。
テキストファイル以外だった場合は、FALSEを返してコンソールにエラーを出します。
文字コードは、Shift_JISなら「Shift_JIS」を指定。空なら「UTF-8」です。省略はできません。指定とファイルの形式が違っていると、化けます💧
実際のファイルを見てどうこうは出来ず、先に指定するしかないっぽい。
画像ファイル開時
引数: ファイルの|ファイルを
ファイル選択やドラッグ&ドロップで取得したファイルオブジェクトを指定して、画像ファイルを開いてImageオブジェクトを返します。
画像ファイル以外だった場合は、FALSEを返してコンソールにエラーを出します。
オーディオファイル開時
引数: ファイルの|ファイルを
ファイル選択やドラッグ&ドロップで取得したファイルオブジェクトを指定して、オーディオファイルを開いてAudioオブジェクトを返します。
オーディオファイル以外だった場合は、FALSEを返してコンソールにエラーを出します。
データファイル開時
引数: ファイルの|ファイルを
なんか、あんま分かんないけど、テキスト、画像、オーディオは、それぞれの形式に合わせて処理を行っているので、そのどれでもないヤツがあった時のために、FileReaderのresultをまんま返すの作ってみただけです。
サンプル
!「https://n3s.nadesi.com/plain/nadesiko3-FileReader.js」を取込む。
テスト=ファイル選択作成。
テストでファイル選択した時には、
ファイル=対象[0]。
# テキスト
空でファイルのテキストファイル開いた時には、# UTF-8
対象を表示。
ここまで。
# 画像
ファイルの画像ファイル開いた時には、
[0,0]に対象を画像描画。
ここまで。
# オーディオ
ファイルのオーディオファイル開いた時には、
対象をオーディオ再生。
ここまで。
ここまで。
こうゆうことすると、毎回コンソールにエラー出ちゃうけど、とりあえず一番簡単なサンプル💧
ダウンロード
ダウンロードもしたいよね!
これも、セキュリティ上のアレで任意の場所に保存することは出来ないので、ダウンロードフォルダにダウンロードします。
ダウンロードはローカルのファイルを編集したい場合以外でも使いたいことあるので、元は別途なでしこの関数を作って貼って使っていましたが、このプラグインを取り込んだ時にはこれだけで出来るようにしてみました。
テキストダウンロード
引数: 文字列をファイル名で|ファイル名へ|ファイル名に
文字列をファイル名でダウンロードします。
JPGダウンロード
引数: ファイル名で品質の|ファイル名へ|ファイル名に
描画中キャンバスをファイル名と品質を指定してJPG形式でダウンロードします。
品質は0~1。1が最高品質です。省略はできません。
なでしこさんには描画ダウンロード
があり、描画中キャンバスをPNG形式でダウンロードすることが出来ますが、JPGでもダウンロードしたいと思って。
PNGダウンロード
引数: ファイル名で|ファイル名へ|ファイル名に
描画中キャンバスをファイル名を指定してPNG形式でダウンロードします。
なでしこさんの描画ダウンロード
はファイル名が固定なので、JPGとお揃いで指定出来るようにしただけ。
サンプル
!「https://n3s.nadesi.com/plain/nadesiko3-FileReader.js」を取込む。
画像URL=「https://n3s.nadesi.com/image.php?f=8.jpg」
描画中キャンバスの「幅」に320をDOM属性設定。
描画中キャンバスの「高さ」に240をDOM属性設定。
#画像ダウンロード
[0,0,320,240]に画像URLを画像描画。
JPGダウンロードボタン=「JPGダウンロード」のボタン作成。
PNGダウンロードボタン=「PNGダウンロード」のボタン作成。改行作成。改行作成。改行作成。
JPGダウンロードボタンをクリックした時には、
ファイル名=「test.jpg」
品質=1。# 0~1
ファイル名で品質のJPGダウンロード。
ここまで。
PNGダウンロードボタンをクリックした時には、
ファイル名=「test.png」
ファイル名でPNGダウンロード。
ここまで。
#テキストダウンロード
テキストエリア=「だうんろーどてすと」のテキストエリア作成。改行作成。
テキストダウンロードボタン=「テキストダウンロード」のボタン作成。
テキストダウンロードボタンをクリックした時には、
ファイル名=「test.txt」
ファイル名でテキストエリアのテキスト取得をテキストダウンロード。
ここまで。
おわります
大本を作ったのはだいぶ前なので、作った時のあれやこれやはもう忘れましたので、できたのできないのと騒ぐこともなく淡々とリファレンス的な?
ただ、エディタで実行する際に、クリアしてもなくならない要素(WINDOWとかエディタに元から用意されているキャンバスなど)へイベント設定していた場合、クリアしてもその設定が残っちゃうことに気づき、!クリア
でremoveEventListener
するように直したんですが、それがなかなか難解でした。
引数のイベントと関数が一致してないとダメだし、関数は無名関数じゃダメなんですって><
参考
https://developer.mozilla.org/ja/docs/Web/API/FileReader
https://www.codegrid.net/articles/fileapi-1/
https://developer.mozilla.org/ja/docs/Web/API/EventTarget/removeEventListener
以前作った、ひととおりのことをお試しするテスト。
実際のところみんな賢いから、なんの説明もなくてもこんだけ見てちゃんと使ってくださる🙏
感謝
- ユメミノウツツさん作
去年のアドベントカレンダーで記事も書いてくださっていますよ!
- shikiishiさん作
アニメーション作成のツールになるそうです☆