本チュートリアルでは、upload.cgiを使用してCGI経由でFlashAirにファイルをアップロード(書き込み)する方法を解説します。

概要

画像などのファイルをFlashAirにアップロードするにはupload.cgiを使用します。
このチュートリアルでは、ウェブ向けチュートリアル / コンテンツリストの取得2 をベースとして、 ファイルをアップロードする方法を解説します。 jQueryも引き続き利用しています。

注意

本機能を誤って使用すると、FlashAirのファイルシステムを破壊してデータを失う恐れがあります。 PCなどのSDメモリカードホスト機器はSDメモリカードの内容(FAT)をキャッシュしている場合がありますが、 本CGIで行った変更をSDメモリカードホスト機器が認識する方法がありません。 そのため、本CGIとSDメモリカードホスト機器から同時に変更を行うとFAT不整合が起こる可能性があります。
CGIからの書き込み後は必ずカードをいったん抜いて再挿入するなどしてSDメモリカードホスト機器に再認識させてください。
Update FlashAirを再挿入せずに読み込む方法を説明したFlashAirを再読み込みするチュートリアルを公開しました。(2018/5)

事前準備

まず、アップロード手順を復習しておきましょう。

  1. CONFIGファイルに、UPLOAD=1を書き込む
  2. FlashAirを再起動する
  3. FlashAirに無線LAN接続する
  4. WRITEPROTECTコマンドで、SDメモリカードホスト機器からの書き込みを禁止する
  5. UPDIRコマンドで、アップロード先フォルダを設定する
  6. FTIMEコマンドで、ファイルの作成日時を設定する
  7. upload.cgiにファイルをPOSTし、ファイルをアップロードする

以下、3番までが完了しているものとして解説していきます。

画面レイアウトの作成

ブラウザユーティリティ本体となるHTMLファイルを作成します。 コンテンツリストの取得1に、 アップロードするファイルを選択するためのテキストボックスおよびファイル選択画面を開くボタンと、 アップロード実行を指示するボタンを追加しています。

/SD_WLAN/List.htm (抜粋)

upload<br>
<input type="file" id='file' name='file'><br>
<button id="cmdUpload">Upload</button>

コードの作成

ファイルをアップロードするには、upload.cgiに対してPOSTコマンドを発行し、 ファイル名とファイル本体を、マルチパート・フォームデータ形式で送信します。 今回は、フォームデータの作成に、XMLHttpRequest Level 2 (XHR2) のFormDataオブジェクトを利用します。

また、データを送る前に、書き込み禁止設定、アップロード先フォルダの設定、ファイルの日時の設定を行っておきます。 今回は、アップロード先フォルダとして現在表示されているフォルダを、日付には現在の日時を使用します。

V1: ファームウェア1.0系では長いファイル名のファイルを送ると、短い名前に変更されます。

送信が終わったら、ファイルリストを読み込み直して、ファイルがアップロードされたことがわかるようにしてみましょう。

実際に見ていきましょう。
main.jsにアップロードを行う関数を作成し追加します。

/SD_WLAN/js/main.js (抜粋)

//UploadProcess
function doUpload() {
    var path = makePath(".");
    var cgi = "/upload.cgi";
    var timestring;
    var dt = new Date();
    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);
    timestring = "0x" + (year + month + date).toString(16) + (hours + minites + seconds).toString(16);  
    $.get(cgi + "?WRITEPROTECT=ON&UPDIR=" + path + "&FTIME=" + timestring, function() {
        var uploadFile = $('#file')[0].files[0];
        var fd = new FormData();
        fd.append("file", uploadFile);
        $.ajax({ url: cgi,
            type: "POST",
            data: fd,
            processData: false,
            contentType: false,
            success: function(html){
                if ( html.indexOf("SUCCESS") ) {
                    alert("success");
                    getFileList(".");
                }else{
                    alert("error");
                }
            }
        });     
    }); 
    return false;
}
  • 6行目-13行目 ファイルの日付を作成しています。 日付、時刻をそれぞれ16ビットの16進数として作成し、合わせて32ビットの1つの値として渡します。 詳しくはAPIガイド / upload.cgiを参照してください。

  • 14行目 書き込み禁止と保存先フォルダ、ファイル日時の各パラメータを設定しています。 ファイル本体の送信がパラメータの送信完了前に行われないように、設定が成功した場合のコールバック関数の中で行います。

  • 15-17行目 マルチパート・フォームデータ形式のデータを作成している部分です。 ファイル選択用テキストボックスからファイル名を読み取り、FormDataに設定しています。

  • 18-31行目 データをPOSTする部分です。 processData(21行目)は、FormDataの内容がURLクエリ文字列として展開されてしまうのを避けるため、falseにする必要があります。 contentType(22行目)は、falseを与えておくとFormDataから読み取って自動的に適切に設定されます。 詳細はjQueryのドキュメントを参照してください)

  • 23-30行目 ファイル本体の送信が成功すると、コールバック関数が呼ばれてフォルダのファイルリストを再読み込みします。

Document Readyメソッドに、送信開始ボタンをクリックした時のイベントを登録する処理を追加します。

/SD_WLAN/js/main.js (抜粋)

$("#cmdUpload").click(function(e) {
    doUpload();
    return false;
});

実行結果

コードをFlashAirに置いたら、FlashAirに無線LAN接続したPCまたはスマートフォンのブラウザで確認してみましょう。 例えば、以下のような画面が表示されるでしょう。

Advanced Tutorial 2 Result

サンプルコード

advanced_tutorial_02.zip (4KB)

このサイトのサンプルコードは二条項BSDライセンスで提供されています。


使用上の注意

重要 アクセス制限不備の脆弱性について

アップロード機能とインターネット同時接続機能が同時に有効な場合、FlashAirに記録されているファイルやデータを改ざんされたり、任意の Lua スクリプトを実行されたりする可能性があります。

インターネット同時接続機能を同時に有効にする場合は、ウェブサーバへの接続時に認証を要求するよう、下記のCONFIGパラメータを設定してください。

  • HTTPDMODE — 認証方法
  • HTTPDUSER — Basic認証のユーザ名
  • HTTPDPASS — Basic認証のパスワード、Digest認証のハッシュ値

脆弱性に関してはFAQもあわせて参照ください。