サーバー構築不要!スマートフォンアプリ向けの新クラウド

トップ >ドキュメント >チュートリアル(JavaScript & Monaca):Monacaアプリからファイルストアを使う

チュートリアル(JavaScript & Monaca)

Monacaアプリからファイルストアを使う

概要

このチュートリアルでは、「中古品交換アプリ」を例に
Monacaアプリから以下の機能を利用する方法について紹介していきます。

  • 会員管理・認証機能
  • ファイルストア機能

後半では、ファイルストアの使い方を説明していきます。

前半はこちら

ファイルストアを利用する

写真のアップロードを行う

以下のHTMLは、新しく中古品の情報を登録する画面のものです。

<ons-page ng-controller="AddItemController">
    <ons-toolbar>
        <div class="right">
            <ons-toolbar-button ng-click="cancelAddItem();">戻る</ons-toolbar-button>
        </div>
        <div class="center">中古品追加</div>
    </ons-toolbar>
    <ons-list modifier="inset" style="margin-top: 10px">
        <ons-list-item class="to-wrapper">
            <ons-row>
                <ons-col width="52px">
                    <img src="image/test.png" width="42" class="to-image">
                </ons-col>
                <ons-col>
                    <div class="to-name"></div>
                    <div class="to-email">zhao.wenhao@stf.nifty.co.jp</div>
                </ons-col>
            </ons-row>
        </ons-list-item>
        <ons-list-item>
            <input type="text" class="text-input text-input--transparent"
                placeholder="中古品の名" style="width: 100%" ng-model="itemTitleAdd">
        </ons-list-item>
        <ons-list-item>
            <textarea class="textarea textarea--transparent"
                placeholder="中古品の説明" style="width: 100%; height: 100px;"
                ng-model="itemDescAdd"></textarea>
        </ons-list-item>
        <ons-list-item modifier="chevron" ng-click="takePhoto();">
            <ons-icon icon="fa fa-camera" style="opacity:0.2; size:20px"></ons-icon>
            <span>写真を撮る</span>
        </ons-list-item>
        <ons-list-item>
            <div class="photo-container"><img id="photoPreview" src="" width="120" height="150"></div>
        </ons-list-item>
    </ons-list>
    <div class="add-button">
        <ons-button modifier="large" style="margin: 0 auto;" ng-click="addNewItem();">保存</ons-button>
    </div>
</ons-page>

モバイル端末で実際に写真を撮るメソッドは、
AddItemControllerに用意しています。
Cordova の Camera API を使用して写真を撮ることができます。

$scope.takePhoto = function() {

    //Camera APIを利用して写真を撮影
    navigator.camera.getPicture (onSuccess, onFail,
        { quality : 100,
          destinationType : Camera.DestinationType.DATA_URL,
          sourceType : Camera.PictureSourceType.CAMERA,
          encodingType: Camera.EncodingType.JPEG,
          targetWidth: 120,
          targetHeight: 150,
          popoverOptions: CameraPopoverOptions,
          saveToPhotoAlbum: false });

    function onSuccess (imageData) {
        // Save photo data into the photoCache.
        $scope.addItemPhotoCache = imageData;
        // Show it before it is saved or not.
        document.getElementById("photoPreview").src = "data:image/jpeg;base64," + $scope.addItemPhotoCache;
    }

    function onFail (message) {
        ons.notification.alert({
            message: message,
            title: "Error",
            buttonLabel: "OK",
            animation: "default"
        });
    }
};

カメラで撮影した写真データはBase64形式ですが、
ファイルストアに写真を保存する場合はBlob形式に変換する必要があります。
以下のサンプルコードを参考に、Base64形式をBlob形式に変換するメソッドを用意してください。

function toBlob(base64) {
    var bin = atob(base64.replace(/^.*,/, ""));
    var buffer = new Uint8Array(bin.length);
    for (var i = 0; i < bin.length; i++) {
        buffer[i] = bin.charCodeAt(i);
    }
    try {
        var blob = new Blob([buffer.buffer], {
            type: "image/jpeg"
        });
    } catch (e) {
        return false;
    }
    return blob;
}

中古品情報を保存するメソッドは以下の通りです。
ファイルストアに写真データを保存するためにNCMBFileクラスを利用し、
中古品情報を保存するためにNCMBObjectを利用しています。

$scope.addNewItem = function() {
    if ($scope.itemTitleAdd == "" || $scope.itemDescAdd == "") {
        ons.notification.alert({
            message: "中古品情報を入力してください。",
            title: "Error",
            buttonLabel: "OK",
            animation: "default"
        });
        return;
    }

    //中古品情報を保存するためのNCMBObjectを作成
    var Item = NCMB.Object.extend("Item");
    var item = new Item();
    item.set("itemTitle", $scope.itemTitleAdd);
    item.set("itemDesc", $scope.itemDescAdd);
    item.set("owner", $scope.currentUserName);

    if ($scope.addItemPhotoCache != null) {
        var photoFileName = Date.now() + "_" + userInfo.userName + ".jpg";

        // Blob形式に変換した写真データをもとに、NCMBFileのインスタンスを作成
        var ncmbFile = new NCMB.File(photoFileName, toBlob($scope.addItemPhotoCache));
        item.set("photoFileName", photoFileName);

        //写真データをファイルストアに保存
        ncmbFile.save().then(function(object) {
            ons.notification.alert({
                message: "写真を保存しました!",
                title: "中古品追加",
                buttonLabel: "OK",
                animation: "default"
            });
        }, function(error) {
            item.set("photoFileName", null);
            ons.notification.alert({
                message: error.message,
                title: "Error",
                buttonLabel: "OK",
                animation: "default"
            });
        });

        $scope.addItemPhotoCache = null;
    }

    //中古品情報をデータストアに保存
    item.save(null, {
        success: function (){
            ons.notification.alert({
                message: "追加に成功しました!",
                title: "中古品追加",
                buttonLabel: "OK",
                animation: "default",
                callback: function() {
                    myNavigator.popPage();
                    tabbar.setActiveTab(2);
                }
            });
        },
        error: function (obj, error){
            ons.notification.alert({
                message: error.message,
                title: "Error",
                buttonLabel: "OK",
                animation: "default"
            });
        }
    });
};

中古品の一覧を表示する

以下のサンプルコードは、中古品情報を表示する画面のHTMLです。
ng-repeat タグと ng-src タグを利用して、
ファイルストアやデータストアから取得した情報を表示しています。

また、ng-if を利用して中古品検索と最新中古品の一覧画面を切り替えるようにしています。

<ons-page ng-controller="ItemListController">
     <ons-toolbar>
         <div class="center">中古品リスト</div>
     </ons-toolbar>

     <div class="navigation-bar">
         <div class="navigation-bar__center">
             <input type="search" class="search-input"
                placeholder="中古品名" ng-model="itemTitleSearch"
                ng-change="ItemSearch(itemTitleSearch);">
         </div>
     </div>

     <div ng-if="itemTitleSearch != ''">
         <ons-list-header class="person-list-header">検索結果</ons-list-header>
         <div ng-if="searchedItemList.length == 0">
             <ons-list>
                 <ons-list-item>
                     <p>なし</p>
                 </ons-list-item>
             </ons-list>
         </div>
         <ons-list>    
             <ons-list-item modifier="chevron" class="list-item-container"
                ng-repeat="searchedItem in searchedItemList"
                ng-click="showSearchedItemDetail($index);">
                 <ons-row>
                     <ons-col width="95px">
                         <img ng-src="" class="thumbnail"/>
                     </ons-col>
                     <ons-col>
                         <div class="title">

                         </div>
                         <div class="owner">

                         </div>
                         <div class="desc">

                         </div>
                     </ons-col>
                     <ons-col width="40px"></ons-col>
                 </ons-row>
             </ons-list-item>
         </ons-list>
     </div>

     <div ng-if="itemTitleSearch == ''">
         <ons-list-header class="person-list-header">最新中古品</ons-list-header>
         <ons-list>    
             <ons-list-item modifier="chevron" class="list-item-container"
                ng-repeat="newItem in newItemList"
                ng-click="showNewItemDetail($index);">
                 <ons-row>
                     <ons-col width="95px">
                         <img ng-src="" class="thumbnail"/>
                     </ons-col>
                     <ons-col>
                         <div class="title">

                         </div>
                         <div class="owner">

                         </div>
                         <div class="desc">

                         </div>
                     </ons-col>
                     <ons-col width="40px"></ons-col>
                 </ons-row>
             </ons-list-item>
         </ons-list>
     </div>
 </ons-page>

中古品情報を取得するメソッドは以下の通りです。
データをまとめて取得するためにNCMBQueryを使用しています。
このNCMBQueryに条件を設定することで、データストアを検索することも可能です。

また、中古品情報に紐付いた写真データは、
NCMBFileのインスタンスでファイル名を指定してfetchメソッドを呼び出し取得しています。

$scope.onLoadNewItemList = function() {

    //Itemクラスを検索するためのNCMBQueryインスタンスを作成
    var Item = NCMB.Object.extend("Item");
    var itemQuery = new NCMB.Query(Item);

    //登録日付の降順でデータを取得するように設定
    itemQuery.descending("createDate");

    //5件データを取得するように設定
    itemQuery.limit(5);

    //自分以外のデータを検索するように設定
    itemQuery.notEqualTo("owner", userInfo.userName);

    //データストアの検索を実行
    itemQuery.find({
        success: function (results) {
            function insertJSONObject(data, results) {
                for (var i = 0; i < results.length; i++) {
                    var item = {};
                    item.itemTitle = results[i].get("itemTitle");
                    item.owner = results[i].get("owner");
                    item.itemDesc = results[i].get("itemDesc");
                    item.photo = results[i].get("photoFileName");
                    item.objectId = results[i].id;
                    data.newItemList[i] = item;
                }
            }

            function getPhotoData(fileName, index) {

                //NCMBFileのインスタンスを作成
                var objFile = new NCMB.File(fileName, null, null, null);

                //ファイルデータを取得
                objFile.fetch().then(function(){
                    $scope.$apply(function() {
                        data.newItemList[index].photo = "data:image/jpeg;base64," + window.btoa(objFile.getData());
                    });
                });
            }

            var data = {};
            data.newItemList = [];
            insertJSONObject(data, results);
            for (var i = 0; i < results.length; i++) {
                getPhotoData(data.newItemList[i].photo, i);
            }
            $scope.newItemList = data.newItemList;
        },
        error: function (error){
            ons.notification.alert({
                message: error.message,
                title: "Error",
                buttonLabel: "OK",
                animation: "default"
            });
        }
    });
};

ファイルストアの使い方については以上です。

前半はこちら

お探しの内容が見つからなかった場合はユーザーコミュニティ もご活用ください。(回答保証はいたしかねます)
なお、 Expertプラン以上のお客様はテクニカルサポートにてご質問を承らせて頂きます。

推奨画面サイズ1024×768px以上

ページの先頭へ