NativeScript でファイルのアップロード(multipart/form-data)
はじめに
NativeScript で アプリ内のファイル、フォトライブラリの 画像/動画、カメラで撮影した画像/動画 をアップロード(multipart/form-data)する方法。
TL;DR
- axios + form-data でのアップロードは不可
- ファイルアップロード無しの単純な API Request なら axios でも可能
- nativescript-background-http でアップロード
- iOS で フォトライブラリやカメラを使う場合、一度アプリ内にファイルを保存する必要がある
目次
環境・条件
1 | $ sw_vers |
- iPhone 11 Pro: iOS 13.3
- Android HUAWEI nova lite 2: Android 9 (ビルド 9.1.0.160)
詳細
axios + FormData 使用不可
NativeScript で axios + form-data でファイルアップロード含む API リクエストを試そうとしたところ、アプリが起動しない状態となった。
参考: axios で添付ファイルありのリクエスト(multipart/form-data の POST)
試したのは下記パッケージ。
form-data - npm
formdata-node - npm
1 | // どちらを使ってもダメ |
Fatal JavaScript exception - application has been terminated.
, JS ERROR TypeError: undefined is not an object (evaluating 'global.process.version.slice')
のエラーでアプリが起動しない。
エラー詳細は下記。
1 | ***** Fatal JavaScript exception - application has been terminated. ***** |
解決方法: background-http を使う
参考にしたページ
- NativeScript/nativescript-background-http: Background Upload plugin for the NativeScript framework
- javascript - How to upload file using multipart form data in nativescript? - Stack Overflow
- vuejs2 - How to upload file in Nativescript Vue - Stack Overflow
- nativescript-background-http/Home.vue at master · NativeScript/nativescript-background-http
- NativeScript/sample-ImageUpload: An integration of nativescript-image-picker and nativescript-background-http
セットアップ
1 | $ tns plugin add nativescript-background-http |
Step1: アプリ内のファイルを選択
実装サンプル
まずはサンプルコード
1 | <template> |
ざっくり解説。
ファイルパスが必要なので tns-core-modules/file-system
を利用。fs.path.normalize
と fs.knownFolders.currentApp().path
を組み合わせて画像ファイルへのパスを取得。
1 | import * as fs from 'tns-core-modules/file-system'; |
bgHttp.session('key')
でセッションを初期化、同時並行で複数セッションを扱うような場合は 'key'
部分を重複しないものにする。
第2引数(request
)に URL などの情報を設定。利用可能なパラメータは Upload request and task API を参照、Android only なパラメータが結構ある。
他入力値がなければ(ファイル単体のアップロードならば) uploadFile
、そうでなければ multipartUpload
を使う。
multipartUpload
を使う場合は、POST パラメータはオブジェクトの配列で設定する。
uploadFile
, multipartUpload
の戻り値(task
)に対して、イベントハンドラが設定可能。進行状況、完了、キャンセルなどのイベントをハンドリングできる。詳しくは Handling upload events
を参照。
1 | { on: 'progress', |
Step2: ImagePicker を利用
nativescript-imagepicker を使って、フォトライブラリの画像を選択してアップロード。
参考:
- NativeScript/sample-ImageUpload: An integration of nativescript-image-picker and nativescript-background-http
- NativeScript で フォトライブラリの 画像や動画 を参照
app/App_Resources/iOS/Info.plist
を編集
1 | ... |
nativescript-permissions
を追加。Android で外部ストレージ(SDカード など)の参照権限要求に利用する。
※nativescript-imagepicker をインストールすると追加されているはず。
1 | $ tns plugin add nativescript-permissions |
実装サンプル
サンプルコード
1 | <template> |
ざっくり解説。
ImagePicker 自体の使い方は NativeScript で フォトライブラリの 画像や動画 を参照 を参照。
画像選択後の処理を setImage
で実施している。
1 | setImage(imageAsset) { |
コメントで書いている通り、Android は imageAsset.android
に画像ファイルのパスが設定されているのでそれを利用すれば良いが、iOS の場合はファイルパスが無いのでいったん保存する必要がある。
参考: comment-400560349 - IOS : Selected image is empty · Issue #197 · NativeScript/nativescript-imagepicker
保存先は fs.knownFolders.documents()
で取得、アプリ内のユーザーからは見えない場所に保存する。ImageSource.fromAsset
で読み込んで、saveToFile
で拡張子を png
にして保存している。
あとは Step1 と同じ流れでリクエストすればよい。
参考: Base64 でアップロード
試してはないが Base64 でのアップロードも可能なようで、その場合はファイルを保存する必要はない。
Step3: カメラを利用
NativeScript/nativescript-camera を使って、撮影した画像をアップロード。
参考: NativeScript でカメラの利用(写真の撮影)
サンプルコード
1 | <template> |
ざっくり解説。
camera 自体の使い方は NativeScript でカメラの利用(写真の撮影) を参照。
画像撮影後の処理を ImagePicker のときと同じく setImage
で行えば良い。
カメラを使うか、フォトライブラリから選択するかを action
で選択させるようにしている。
補足: ファイルアップロードがなければ axios 自体は利用可能
axios
でファイルアップロードする場合に必要な form-data
が使えないというだけなので、axios
自体は問題なく利用可能。
API の検証には JSONPlaceholder - Fake online REST API for developers を使った。
1 | <template> |
まとめ
- axios + form-data でのアップロードは不可
- ファイルアップロード無しの単純な API Request なら axios でも可能
- nativescript-background-http でアップロード
- iOS で フォトライブラリやカメラを使う場合、一度アプリ内にファイルを保存する必要がある
その他・メモ
2020/05/01 追記
今からなら klippa-app/nativescript-http を試してみるのもありそう。
参考文献
- NativeScript/nativescript-background-http: Background Upload plugin for the NativeScript framework
- javascript - How to upload file using multipart form data in nativescript? - Stack Overflow
- vuejs2 - How to upload file in Nativescript Vue - Stack Overflow
- nativescript-background-http/Home.vue at master · NativeScript/nativescript-background-http
- NativeScript/sample-ImageUpload: An integration of nativescript-image-picker and nativescript-background-http
- IOS : Selected image is empty · Issue #197 · NativeScript/nativescript-imagepicker
- JSONPlaceholder - Fake online REST API for developers
- klippa-app/nativescript-http
関連記事
- NativeScript, JsBarcode でバーコードを 生成/描画
- NativeScript でデバイスの輝度(明るさ)を制御する
- NativeScript-Vue でネイテイブアプリの開発(チュートリアル + α)
- NativeScript で生体認証(FaceID, TouchID, Android 指紋認証)
- NativeScript-Vue で QRコードの読取り
- NativeScript で入力範囲外タップでキーボードを非表示にする
- JavaScript で URL のクエリパラメータを操作する方法
- jQuery Select2 で、初期値の設定と選択状態のクリア