FlashAirへのアップロード
第5回では、FlashAirへファイルをアップロードするアプリを作成します。upload.cgiを使用します。
事前準備
1. プロジェクトを作成する
まずは作成するアプリのプロジェクトを作成します。 前回までと同じく、プロジェクトを作成したいディレクトリへ移動し、以下のコマンドを実行します。
> cordova create cordovatutorial5 com.fixstars.flashair.tutorial CordovaTutorial5
また、プロジェクト作成後、browserプラットフォーム及び以下のプラグインの追加を行ってください。
- 第2回で使用したプラグイン
- Statusbarプラグイン(
config.xml
へのコード追加作業含む)
- Statusbarプラグイン(
- 第3回で使用したプラグイン
- Fileプラグイン
- FileTransferプラグイン
- Inappbrowserプラグイン
2. 第4回で使用したファイルを追加する
第4回で使用したファイルを以下のようにコピーして追加します。
cordovatutorial5 ├─ hooks ├─ platforms ├─ plugins ├─ www │ ├─ css │ │ └─ load.css(上書きコピー) │ ├─ img │ │ └─ logo.png │ ├─ js │ │ ├─ jquery-3.1.1.min.js(上書きコピー) │ │ ├─ load.js(上書きコピー) │ │ ├─ tutorial2.js(上書きコピー) │ │ ├─ tutorial3.js(上書きコピー) │ │ └─ tutorial4.js(上書きコピー) │ ├─ index.html(上書きコピー) │ ├─ tutorial2.html(上書きコピー) │ ├─ tutorial3.html(上書きコピー) │ └─ tutorial4.html(上書きコピー) └─ config.xml
アプリのトップ画面作成
1. index.htmlを編集する
アプリのトップ画面であるindex.html
を編集します。第4回の36~41行目を、以下のように変更してください。
/www/index.html
<p class="pos-center"><button type="button" onclick="location.href='tutorial2.html'">2.コンテンツリストの取得</button></p>
<p class="pos-center"><button type="button" onclick="location.href='tutorial3.html'">3.コンテンツのダウンロード</button></p>
<p class="pos-center"><button type="button" onclick="location.href='tutorial4.html'">4.サムネイルの表示</button></p>
<p class="pos-center"><button type="button" onclick="location.href='tutorial5.html'">5.FlashAirへのアップロード</button></p>
<script type="text/javascript" src="cordova.js"></script>
<script type="text/javascript" src="js/load.js"></script>
</body>
- 39行目
タップされたらtutorial5.html
の画面へ遷移するボタンを追加しています。FlashAirへのアップロードはtutorial5.html
の画面で行います。
2. 実行結果
上記の編集が完了したら、ビルドを行い、出来上がったアプリのインストールを行ってください。第4回と比べて、「5.FlashAirへのアップロード」ボタンを追加しています。
Androidデバイスの場合
iOSデバイスの場合
FlashAirへのアップロード画面の作成
1. tutorial5.htmlを作成する
続いて、FlashAirへのアップロード画面を作成します。tutorial4.htmlとの共通部分が多いので、コピーしたファイルをtutorial5.html
として保存して、9~24行目を以下のように変更してください。
/www/tutorial5.html
<title>Tutorial5</title>
<link rel="stylesheet" type="text/css" href="css/load.css">
</head>
<body onload="onLoad()">
<div id="header" class="pos-center">
<div id="head-left"><<br>Back</div>
<h1 id="head-center">Upload</h1>
<div id="head-right"></div>
</div>
<div id="list"></div>
<hr>
<div id="upload">
<h3>Upload the file to the current directory</h3>
<button id="doUpload">Upload!</button>
</div>
<hr>
<script type="text/javascript" src="cordova.js"></script>
<script type="text/javascript" src="js/jquery-3.1.1.min.js"></script>
<script type="text/javascript" src="js/tutorial5.js"></script>
</body>
</html>
</html>
- 9行目
画面のタイトルをTutorial5
に変更しています。 - 15行目
ヘッダーのタイトルをUpload
に変更しています。 - 20-23行目
FlashAirへアプリ内に格納しているファイルをアップロードするボタン枠を追加しています。 アップロードするファイルについては後述します。 - 27行目
ロードするJavaScriptの内、tutorial4.js
をtutorial5.js
へ変更しています。
2. tutorial5.jsで使用するプラグインを追加する
次はtutorial5.js
の作成に移りますが、その前にアップロード処理時の確認用ダイアログを使えるようにするため、Dialogsプラグインを追加していきます。 追加コマンドは以下の通りです。
> cordova plugin add cordova-plugin-dialogs -save
3. tutorial5.jsを作成する
FlashAirへアップロード画面でロードするtutorial5.js
を作成していきます。tutorial4.jsとの共通部分が多いので、コピーしたファイルを
tutorial5.js
として保存して、まず9~21行目を以下のように変更してください。
/www/js/tutorial5.js
function onDeviceReady(){
getFileList("");
$(document).on("click", "a.dir", function(){
getFileList(this.text);
});
$(document).on("click", "a.file", function(){
downloadFile(this.text, currentPath);
});
$("#doUpload").click(function(){
navigator.notification.confirm("Are you sure you upload 'upload.jpg'?", confirmCallback, "UPLOAD", "YES,NO");
function confirmCallback(buttonIndex) {
switch (buttonIndex) {
// Dialog closed without tapped any buttons.
case 0:
break;
// "YES" tapped
case 1:
uploadFile();
break;
// "NO" tapped
case 2:
break;
}
}
});
document.addEventListener("backbutton", onBackKeyDown, false);
$("#head-left").click(function(){
onBackKeyDown();
});
}
- 17-18行目
「Upload!」ボタンをタップしたときに、まず確認用のダイアログを表示させます。 確認ダイアログの表示にはDialogsプラグインのnavigator.notification.confirmを使用します。 第1引数がメッセージ、第2引数がコールバック関数、第3引数がタイトル、第4引数がボタン名の配列になります。 - 19-32行目
コールバック関数の中身です。 今回の場合は「YES」ボタンをタップしたときのみ、uploadFile
関数が呼び出されるように設定しています。
続いて以下のアップロード処理について、最後の行(179行目)から追加してください。 尚、コードは上級者向けチュートリアル - FlashAirへのアップロード を元にしていますが、inputタグを使ったファイルアップロードがAndroid 4.4(Kitkat)で使用できない為、マルチパートの構造を自作してPOSTする方法をとっています。
/www/js/tutorial5.js
// Upload the content.
function uploadFile(){
var uppath = makePath(".");
var cgi = "http://flashair/upload.cgi";
var dt = new Date();
// The range of years for FAT32 is from 1980 to 2107.
var year = (dt.getFullYear() - 1980) << 9;
var month = (dt.getMonth() + 1) << 5;
var date = dt.getDate();
var hours = dt.getHours() << 11;
var minites = dt.getMinutes() << 5;
var seconds = Math.floor(dt.getSeconds() / 2);
var timestring = "0x" + (year + month + date).toString(16) + (hours + minites + seconds).toString(16);
var param = cgi + "?WRITEPROTECT=ON&UPDIR=" + uppath + "&FTIME=" + timestring;
// GET request upload.cgi parameters.
$.get(param, function(){
// Create boundary.
var boundary = "--------------------FlashAir" + year.toString() + month.toString() + date.toString() + hours.toString() + minites.toString() + seconds.toString);
var localReq = new XMLHttpRequest();
var preReader = new FileReader();
var sufReader = new FileReader();
var localBuffer, faBuffer;
// GET request upload file (as ArrayBuffer).
localReq.open("GET", "img/upload.jpg", true);
localReq.responseType = "arraybuffer";
// POST request to FlashAir succeeds.
var faReqSuccess = function(){
navigator.notification.alert("Upload complete!", function(){
// Update the content list.
getFileList(".");
}, "UPLOAD", "OK");
};
// Suffix loading succeeds.
var sufReaderSuccess = function(){
// Connect HTTP Body suffix.
faBuffer = connectBuffer(faBuffer, sufReader.result);
var faReq = new XMLHttpRequest();
// Make a POST request to upload a file to FlashAir.
faReq.open("POST", cgi, true);
// Set HTTP Headers.
faReq.setRequestHeader("Content-Type", "multipart/form-data; boundary=" + boundary);
faReq.onload = faReqSuccess;
faReq.send(faBuffer);
};
// Prefix loading succeeds.
var preReaderSuccess = function(){
// Connect HTTP Body prefix and upload file.
faBuffer = connectBuffer(preReader.result, localBuffer);
// HTTP Body suffix
var suffix = "\r\n" + "--" + boundary + "--";
sufReader.onload = sufReaderSuccess;
// Load suffix (as ArrayBuffer).
sufReader.readAsArrayBuffer(new Blob([suffix]));
};
// GET request upload file succeeds.
var localReqSuccess = function(){
localBuffer = localReq.response;
// HTTP Body prefix
var prefix = "--" + boundary + "\r\n" + "Content-Disposition: form-data; name=\"userfile\"; filename=\"upload.jpg\"\r\n" + "Content-Type: image/peg\r\n\r\n";
preReader.onload = preReaderSuccess;
// Load prefix (as ArrayBuffer).
preReader.readAsArrayBuffer(new Blob([prefix]));
};
localReq.onload = localReqSuccess;
localReq.send(null);
});
return false;
}
// Add "addBuffer" to "oriBuffer" (as ArrayBuffer).
function connectBuffer(oriBuffer, addBuffer){
var uint8Array = new Uint8Array(oriBuffer.byteLength + addBuffer.byteLength);
uint8Array.set(new Uint8Array(oriBuffer), 0);
uint8Array.set(new Uint8Array(addBuffer), oriBuffer.byteLength);
return uint8Array.buffer;
}
- 181-194行目
まずはupload.cgi
のパラメータを確定させ、GETリクエストを行っています。 各パラメータについてはupload.cgiをご確認ください。 - 202-203,242-243行目
アプリ内に置いてあるファイル(img/upload.jpg
)をGETリクエストしています。responseType
にはarraybuffer
を指定して、バイナリデータとして取り扱います。 リクエスト成功時のコールバック関数はlocalReqSuccess
です。 - 205-210行目
faReqSuccess
(220行目)のコールバック関数の中身です。 Dialogsプラグインのnavigator.notification.alertを使用したアラートダイアログを表示します。第1引数がメッセージ、第2引数がアラートダイアログを閉じたときに呼ばれるコールバック関数、第3引数がタイトル、第4引数がボタン名になります。そしてコールバック関数の中で、getFileList(".")
を呼び出すことでコンテンツリストが更新され、アップロードしたファイルが確認できるようになります。 - 212-222行目
sufReaderSuccess
(229行目)のコールバック関数の中身です。upload.cgi
を使用して、FlashAirへ「upload.jpg」をPOSTリクエストしています。 リクエスト成功時のコールバック関数はfaReqSuccess
です。 - 224-232行目
preReaderSuccess
(238行目)のコールバック関数の中身です。FileReader.readAsArrayBuffer()
を利用して、HTTPボディ部のアップロードファイル本体の後につけるString(suffix
)をArrayBufferとして読み出すようにしています。 読み出し成功時のコールバック関数はsufReaderSuccess
です。 - 234-241行目
localReqSuccess
(242行目)のコールバック関数の中身です。FileReader.readAsArrayBuffer()
を利用して、HTTPボディ部のアップロードファイル本体の前につけるString(prefix
)をArrayBufferとして読み出すようにしています。 読み出し成功時のコールバック関数はpreReaderSuccess
です。 - 248-253行目
元のArrayBufferに追加したいArrayBufferを追加して返す関数です。
4. tutorial5.jsで指定している画像を追加する
tutorial5.js
で指定したアップロード用の画像を/www/img
以下に保存します。
upload.jpg
5. 実行結果
上記の編集が完了したら、ビルドを行い、アプリのインストールを行います。 アプリインストール後、FlashAirへ無線LAN接続していれば、トップ画面の「5.FlashAirへのアップロード」ボタンをタップしたときに、画面下部にファイルをアップロードするボタンの枠が表示されます。 そして、この中の「Upload!」ボタンをタップすると、表示しているカレントディレクトリに「upload.jpg」ファイルがアップロードされ、コンテンツリストの表示が更新されます。
Androidデバイスの場合
iOSデバイスの場合
サンプルコード
- このサンプルコードはApache License, Version 2.0で提供されています。
- 「cordova_tutorial_05」ディレクトリは、zipファイルで圧縮してPhoneGap Buildへアップロードすることでビルドできます。 ビルド方法はHelloWorldアプリをビルドするをご確認ください。
- Cordovaプロジェクトで確認する場合は、「cordova_tutorial_05」ディレクトリ内のデータをプロジェクト内へ上書きコピーしてください。