今回やったこと
IonicベースのアプリでAndroid・iOS問わずファイル選択画面→読み込みを実装しました。
※文字コード変換付き
悪戦苦闘
Ionicベースのアプリ開発中にユーザーの任意のファイルをロードしたくなりました。でもAndroidでもiOSでもというのが意外と大変で...stackoverflowにもスレが結構立っています。
初手
Ionic native APIのFile APIを利用。でもこれ、読み込みファイルのパスわかる前提で「ドコドコにあるファイルを読み込むよー」的なところから使うもの...今回はパスもわからないんですごめんなさい...。
次手
一旦iOS対応は諦めてAndroidのみ対応なnative APIのFile Chooser APIを利用。ファイルを選ばせてくれるらしい。Windowsでいうエクスプローラー、MacOSでいうFinderかな?
この子はファイルまでのURI(content://path/to.file
という形式)を拾ってきてくれるので、あとはこれを参照するためにHTTP APIを利用。
ところがどっこい怒られた。
エラー:HttpURLConnection Invalid HTTP method: content
AndroidのcontentメソッドはHTTP APIでは読めませんでした。
いろいろ考えましたが...。
「そういえばIonicってもともとHTMLなんだから、formで送信すれば良くないですか」と気づきました。
一度Ionicで使えるForm送信を試してみましたが、type="file"
だとうまくいかなかったです。(リンク先のIonicのサイトにもtextとかselectしか例がない...うまくいったら教えてくださると助かります)
最終結果。
大筋は先程のform利用と同じですが、<form></form>
は使わずに<input type="file">
の変更検知でうまくいきました。
<label for="js-import-file__form">読み込むファイル</label>
<input id="js-import-file__form" (change)="fileUp($ev)" type="file">
<button id="js-import-file__submit" (click)="submitNewFile()" ion-button block disabled="disabled">読み込み</button>
// クラスのフィールド
// のちのち書き込みとかで native API の File を使うときは
// 型名が競合してしまうので File ではなく any に。
private inputFile: any;
// file選択フォームの値(=選択ファイル)を変更すると発火
public fileUp(ev: Event) {
this.inputFile = (<HTMLInputElement>ev.srcElement).files[0];
// ファイル非選択時はButtonをdisabledにします
if (this.inputFile.name) { // ファイルが選択されているとき
document.getElementById('js-import-file__submit').removeAttribute('disabled');
} else { // ファイルが選択されていないとき
document.getElementById('js-import-file__submit').setAttribute('disabled', 'disabled');
}
}
// submitボタンおすと発火
submitNewFile() {
// ローディング画面でも表示...
let loading = this.loadingCtrl.create({
spinner: 'circles',
content: '読み込み中...'
});
loading.present();
// Ionic の native API も使えますが、
// もし文字コード変換も行うときは Web API の FileReader 使います。
var reader = new FileReader();
reader.readAsText(this.inputFile, "Shift-JIS");
reader.onload = () => {
// reader.result に読み込んだテキストがいつも通り格納されます。
// console.log(reader.result);
// ローディング画面を解除しましょう...
loading.dismiss();
}
}