Flash の画面をキャプチャして Rails で保存する
久しぶりに FlashDevelop をインストールして ActionScript で遊んでみました。
作ったのは簡単なペイントツールで、描いた絵をサーバ側の Rails で保存するというもの。
調べてみると ActionScript で画面をファイルとして保存するには BitmapData に画面の内容を描画して ByteArray に変換、その後そのバイト列をそのままサーバに送信してサーバ側でファイル保存、という流れでいいみたいですね。
サーバ側への送信前に BitmapData を JPEG 形式にエンコードするために、以下のライブラリに含まれている JPGEncoder クラスを使用しました。
as3corelib - Google Code
http://code.google.com/p/as3corelib/
FlashDevelop では Project ペインの lib フォルダ上で右クリック - 「Add」 - 「Existing File」 でアーカイブに含まれる「as3corelib.swc」 ファイルを選択して読み込みます。
その後読み込んだ as3corelib.swc ファイルを右クリック - 「Add To Library」とすれば使えるようになります。
ActionScript 側での保存処理部分のみ抜粋すると以下のようになります。
var bitmapData:BitmapData = new BitmapData(stage.stageWidth, stage.stageHeight); // 作ったビットマップデータにキャンバス用の Sprite を指定し描画する bitmapData.draw(canvas); // JPEG 形式のバイト列にエンコード var jpgEncoder:JPGEncoder = new JPGEncoder(80); var byteArray:ByteArray = jpgEncoder.encode(bitmapData); var urlRequest:URLRequest = new URLRequest(); urlRequest.url = "http://localhost:3000/example/upload"; urlRequest.contentType = "application/octet-stream"; urlRequest.method = URLRequestMethod.POST; urlRequest.data = byteArray; var urlLoader:URLLoader = new URLLoader(); urlLoader.addEventListener(Event.COMPLETE, onCompleteHandler, false, 0, false); urlLoader.load(urlRequest);
次はサーバサイドの Rails 側です。
今まで Rails で「application/octet-stream」の POST データを扱った事がなかったので、どうするのかと思ったのですが、調べてみるとちゃんと生の Request 送信データを取得する方法が用意されていました。
Class: ActionController::Request
http://api.rubyonrails.org/classes/ActionController/Request.html
ここを読んだ感じでは、Request#body() か Request#raw_post() を使えば良さそうです。
- body()
body()
The request body is an IO input stream. If the RAW_POST_DATA environment variable is already set, wrap it in a StringIO.
- raw_post()
raw_post()
Read the request \body. This is useful for web services that need to work with raw requests directly.
StringIO でラップされている body() を使う方が楽そうなので、以下のような感じで実装してみました。
class ExampleController < ApplicationController UPLOAD_PATH = RAILS_ROOT + "/files" RANDOM_ARRAY = ('a'..'z').to_a + ('A'..'Z').to_a + ('0'..'9').to_a skip_before_filter :verify_authenticity_token ,:only => [:upload] def upload filename = "#{generate_random_string}.jpg" filepath = File.join(UPLOAD_PATH, filename) File.open(filepath, 'wb') do |f| f.write(request.body.read) end render :text => filename end private # ランダムな文字列を作成する。 def generate_random_string(length = 8) Array.new(length) { RANDOM_ARRAY[rand(RANDOM_ARRAY.size)] }.join end end
ランダムに作成した適当なファイル名で、request.body の内容を保存しています。
「skip_before_filter :verify_authenticity_token」は Flash からそのまま POST すると発生する「InvalidAuthenticityToken」用に入れました。
これで Flash 上で描いた画像が Rails 側にちゃんと保存されました。
開発環境
ソフトウェア | バージョン |
---|---|
JDK | 1.6.0_14 |
Flex SDK | 3.4.0.6955 |
FlashDevelop | 3.0.2-RTM |
as3corelib | .92.1 |
Ruby | 1.8.6 |
Rails | 2.2.2 |
参考サイト
Flashから画像ファイルを保存する - FICC LABS
http://www.ficc.jp/labs/archives/ando/flash_img_file/
PNGエンコーダ - Flash OOP Japan
http://cs3book.flashoop.jp/wiki/index.php?PNG%E3%82%A8%E3%83%B3%E3%82%B3%E3%83%BC%E3%83%80