3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

日本語プログラミング言語「なでしこ」Advent Calendar 2023

Day 3

なでしこさんでローカルのファイルを読み込みたい!

Last updated at Posted at 2023-12-02

発端

 なでしこ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」
描画中キャンバス「幅」320DOM属性設定
描画中キャンバス「高さ」240DOM属性設定

#画像ダウンロード
[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

https://gray-code.com/javascript/unset-event-listener/

 以前作った、ひととおりのことをお試しするテスト。
 実際のところみんな賢いから、なんの説明もなくてもこんだけ見てちゃんと使ってくださる🙏

感謝

  • ユメミノウツツさん作

 去年のアドベントカレンダーで記事も書いてくださっていますよ!

  • shikiishiさん作

 アニメーション作成のツールになるそうです☆

3
1
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?