Posted at

AngularJs ✕ Firebaseで爆速イメージストア環境の作成

More than 3 years have passed since last update.

以前、AngularJs ✕ Firebaseで爆速リアルタイムアプリケーションの作成という記事を書きましたが、

今回は画像をさくっとどこかにあげて利用したい時、firebaseを使えば、5分で環境が出来ます。

S3、Parseの利用を検討しましたが、


  • 無料

  • APIドキュメントがわかりやすい(Parseはファイルストレージが20GBだが、ドキュメントがわかりにくい)

  • リアルタイムにデータ同期しやすい

上記の点でAngularJs×Firebaseを採用。なんといってもリアルタイムデータ同期が魅力的。

※Milkcocoaは検討してませんw


Firebaseとは

いわゆるモバイルBassでWebアプリケーション、モバイル・アプリケーションの開発者向けにリアルタイムにスケーラブルなバックエンドサービスを提供しています。

一定の転送量、接続数、容量は無料で、クレジットなしで使用できます。

ストレージ1GBまで無料なので、まぁ問題ないレベル。

バックアップは無料プランでは取れません。

https://www.firebase.com/


AngularFire

そして、AngularJsからFirebaseを利用できる、

AngularFireというAPIも公開されていますので、

バックエンドのコードを書く必要も、サーバも必要なく、

必要な作業に集中できます。

AngularFireのAPIを利用することで、

Angularjsのモデルが自動的に同期され、Firebase上でリアルタイムにデータバインディングされます。

これでhtml側でのview, Angularjsでのmodel, firebaseでストアされたjsonのデータの3wayデータバインディングが可能となります。


angular-file-upload

FlashによるFileAPI代替を提供するモジュール

HTML5のFileAPIを利用,HTML5のFileAPIサポートしていないブラウザ(IE8、IE9など)にはFlashを利用して同等の機能を提供。

今回はbase64データのURL生成してアップロードしています。


サンプル:画像アップロードアプリ


index.html

<script src="https://gist.github.com/manchan/0d8597b1ac131d1b1f16.js"></script>

<noscript><pre><code>

File: index.html
-------------------------

<!doctype html>
<html>
<head>
<!-- AngularJS -->
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.6/angular.min.js"></script>
<!-- Firebase -->
<script src="https://cdn.firebase.com/js/client/2.3.0/firebase.js"></script>
<!-- AngularFire -->
<script src="https://cdn.firebase.com/libs/angularfire/1.1.3/angularfire.min.js"></script>
<!-- Angular-file-upload -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/danialfarid-angular-file-upload/10.1.0/ng-file-upload.js"></script>
<style type="text/css">
.thumb {width: 24px;height: 24px;float: none;position: relative;top: 7px;}
form .progress {line-height: 15px;}
.progress {display: inline-block;width: 100px;border: 3px groove #CCC;}
.progress div {font-size: smaller;background: orange;width: 0;}
ol, ul{list-style:none;}
#content #photo{position: relative;overflow: hidden;}
#content #photo ul{position: relative;left: 50%;float: left;}
#content #photo li{position: relative;left: -50%;float: left;}
#content #photo .r20{margin-left:20px;}
#content #photo li img {width: 420px;height: 420px;}
</style>
</head>
<body>
<div>
<h1>AngularJs practice</h1>
<body ng-app="fileUpload" ng-controller="MyCtrl">
<form name="myForm">
<fieldset>
<legend>Upload on form submit</legend>
Title:
<input type="text" name="userName" ng-model="username" size="31" required>
<i ng-show="myForm.userName.$error.required">*required</i>
<br>Photo:
<input type="file" ngf-select ng-model="picFile" name="file"
accept="image/*" ngf-max-size="2MB" required>
<i ng-show="myForm.file.$error.required">*required</i><br>
<i ng-show="myForm.file.$error.maxSize">File too large
{{picFile.size / 1000000|number:1}}MB: max {{picFile.$errorParam}}</i>
<img ng-show="myForm.file.$valid" ngf-thumbnail="picFile" class="thumb"> <button ng-click="picFile = null" ng-show="picFile">Remove</button>
<br>
<button ng-disabled="!myForm.$valid"
ng-click="uploadPic(picFile)">Submit</button>
<span ng-show="picFile.result">Upload Successful</span>
<span class="err" ng-show="errorMsg">{{errorMsg}}</span>
</fieldset>
<br>
</form>
<div id="content">
<h2>photo</h2>
<div id="photo">
<button type="button" class="btn btn-danger" ng-click="image_all_remove()">All Remove</button>
<ul>
<li ng-repeat="img in images | orderBy:'-submitDate'">
<p>{{img.$key}}:{{img.submitDate}}</p>
<img src="{{img.images}}" alt="" width="{{img.width}}" height="{{img.height}}"/>
</li>
</ul>
</div>
</div>
</body>
<script type="text/javascript">
// 依存モジュールとしてfirebase、ngFileUploadを登録
var app = angular.module('fileUpload', ['ngFileUpload', 'firebase']);
app.controller('MyCtrl', ['$scope','$firebase','$firebaseArray', 'Upload', '$timeout', function ($scope,$firebase, $firebaseArray, Upload, $timeout) {

// "https://<your-firebase>.firebaseio.com/"
var fb = new Firebase(
"https://<your-firebase>.firebaseio.com/");
var ref = fb.child(
"images").orderByChild("submitDate");
var sync = $firebaseArray(ref);
var syncArray = $firebaseArray(fb.child(
"images"));
// ストアされたjson objectをmodelにバインド
$scope.images = sync
$scope.uploadPic = function(file) {
var title = $scope.username;
var submitDate = new Date().toISOString();
var images = Upload.base64DataUrl(file).then(function(base64Urls){

$timeout(function () {
file.result = base64Urls.data;
});

// 同期配列にArray.push
syncArray.$add({
title: title,
images : base64Urls,
submitDate: submitDate
})
.then(function(error) {
if (error) {
console.log("Error:",error);
} else {
console.log(
"Post set successfully!");
}
});
});
};
// 画像全削除
$scope.image_all_remove = function(){
angular.forEach($scope.images, function(img, i){
var row = $scope.images.$getRecord($scope.images[i].$id);
$scope.images.$remove(row);
});
};
}]);
</script>
</div>
</body>
</html>

</code></pre></noscript>


わずか110行で簡単イメージストアアプリが作成できます。

var ref = new Firebase("https://<your-firebase>.firebaseio.com/");



上記の箇所をfirebaseにサインアップして、URLを書き換えるだけですぐ使えます。

サインアップはこちらから

https://www.firebase.com/login/


※注意

無料プランでストレージは1GBまでです。


Firebaseにストアされたデータにindexをはる方法

設定で、json形式でkey,rulesの中に.indexOnを記述するだけ

詳細はこちら

https://www.firebase.com/docs/security/guide/indexing-data.html


Firebaseにストアされたデータのセキュリティに関して

jsonでのセキュリティルールの設定が可能。

認証されたユーザがどのようにデータを変更できるかを決める。

データの転送はSSL経由。

さらなる詳細はこちら

https://www.firebase.com/docs/security/


AngularFireの使用アプリ

好きなアーティストの音楽をランキング順の聴くことができるサービスです。

Recentの箇所をfirebaseでストアしています。

Lamusica

http://manchan.github.io/lamusica/

githubはこちら

https://github.com/manchan/lamusica


AngularFireのドキュメントはこちら

https://www.firebase.com/docs/web/libraries/angular/index.html


ng-file-uploadのドキュメントはこちら

https://github.com/danialfarid/ng-file-upload


おわりに

5分は長すぎたかもしれません。