スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

エキサイトブログ引越ツール Flex & rubyメモ

エキサイトブログ引越ツール作成における技術的メモ。

今回クライアントはFLEX2、サーバはRubyで作成した。
クライアント側は、HTMLでもよかったが、多少リッチにするためにFlexを採用。AJAXも使いたいと思ったが、最近Flexのソースを読むことが多いので、Flexで作成することにした。ただ読むばっかりで書くことが少ないので少し苦戦した。

●cgi
レンタルサーバなので、erubyなどが入れられるかどうかわからない。なので、普通のcgiとして呼び出すことにした。
rubyスクリプトの置かれたディレクトリの.htaccessファイルに

AddHandler cgi-script .rbx

を記述。フロントのスクリプトのみ、このディレクトリに置き、その中でパラメータを受け取り、実際の処理を別のディレクトリにあるクラスを呼び出すようにした。
バックエンドの実際の処理を行うクラスが置かれたディレクトリには、.htaccessに
deny from all
を記述し、Webから直接アクセスさせないようにする。

フロントのスクリプトは、他のユーザからアクセスされていないかチェックするためのスクリプトと実際の処理を仲介するスクリプトの二つ。同時にたくさんのユーザがアクセスしたときの負荷が見えないので、このようにし、他のユーザがスクリプトを走らせている場合は、busyのメッセージを表示するようにした。単純にpsでプロセスをチェックするだけ。

●ブラウザのキャッシュ対策
このスクリプト作成で詰まったのは、ブラウザのキャッシュ。レスポンスのHTTPヘッダに以下をセットすることで回避。

Cache-Control: max-age=0, must-revalidate

なお、Flexのページのダウンロードでも同じことがあったので、こっちは、.htaccessに

<Files *>
Header set Cache-Control: "private, pre-check=0, post-check=0, max-age=0"
Header set Expires: 0
Header set Pragma: no-cache
</Files>

を記述することで対応。

●HTTPService
エクスポート作業は時間のかかる作業なので、スレッドを作成して、サーバ側で作業をして、一旦Flex側にレスポンスを返してから、Flexから進捗状態を定期的に問い合わせるようにしたかったのだが、rubyでスレッドを作って回しても、呼び出し側がレスポンスを返して終了してしまうと、子スレッドも死んでしまう。まあ、cgiでやっているので当然のことだが、JVMが常駐しているアプリケーションサーバ上でのJava開発とはこの辺が事情が違う。
外部シェルを呼び出してやる方法を考えたが、ブラウザから直接rubyスクリプトを呼び出すと、ruby側で標準出力に出力した内容がプログレッシブに表示されるので、同様にFlex側でそれを進捗状態として表示すればいいと考えた。

が、Flex側ではそうは行かなかった。
HTTPServiceを使ってサーバ側と通信を行うのだが、レスポンスをすべて受け取ってから出ないと表示できない。便利なものはそういう制約が付き物だ。オプションを探したが、なさそう。
元のスクリプトでは、進捗表示として、全体数と現在処理中の番号、URLを標準出力に表示していたが、これだと一気にFlex側の進捗欄に表示されてしまう。

これだと意味がないので、ログは表示せず、全部終わってから返すことにした。しかし、こうすると、340記事ぐらいを超えると、「Error #2032: ストリームエラー」となってしまう。多分その間全くレスポンスを返さないからだろうと思って、20ごとに進捗のレスポンスを出力するようにしたがあまり変わらない。
結局、ユーザに期間を区切ってもらうことで回避するという残念な結果となった。やっぱり外部シェルを呼び出す形に変えた方がいいか。ここは要検討。

●E4Xの扱い
あと詰まったのが、レスポンスの受け取り。
まず詰まったのが、
ReferenceError: Error #1069: flash.xml.XMLNode にプロパティ xxx が見つからず、デフォルト値もありません。
lastResultをそのままログ欄に表示しているのだか、そこではきちんと正しいXMLが表示されている。さっぱりわからなかったが、結局、e4x形式を期待していたにも関わらず、ResultFormatをe4xに指定していなかったのが原因だった。しかしガイドのサンプルでは特に何の指定もなかったのだが。
e4xはECMAスクリプトでは、xmlよりも多いと思うが、xpathに比べて優位性がどれだけあるのかは疑問だが、とりあえずそれで処理。

問題はこれだけでは終わらず、resultハンドラで、
xxx.lastResult.yyy.zzz
とアクセスするのだが値が空になる。
これにも長々と解決に時間がかかった。
結局、e4xで処理する場合、ルートノードを入れてはいけないのだった。
xxx.lastResult.root.child1
としては駄目で、
xxx.lastResult.child1
としなければいけない。
Adobeのサイトには、

Note: If the result format is e4x, you do not include the root node of the XML structure in the dot notation when binding to the DataGrid.

なんて書いてあった。e4xの規約なのかと思って調べたがどうもそれらしきことは書いていない。よくわからない。ファーストステップガイドにあるサンプルでは、resultFormatがデフォルトのobjectのためか、ルートノードからアクセスでも問題ない。

●ファイルダウンロード
ファイルダウンロードも少し苦労した。
navigateToURL(new URLRequest(dl_base + event.target.label));
とやってしまうとテキストファイルなので、ブラウザがダウンロード画面を表示せずに、直接表示してしまう。これはあとでFC2ブログにインポートするものなので、テキストでダウンロードしないとよろしくない。またファイルサイズが大きいとブラウザ上での表示も時間がかかる。
.htaccessに、
AddType application/octetstream .txt
とか、application/forcedownloadとか指定するが、ブラウザの改行の表示が崩れる以外は何も変わらない。勝手な解釈はやめてもらいたいものだ。

なので、Flex側で対応することにした。幸い、ダウンロードを行うクラスが用意されている。これは、以下のように、インスタンスのレファレンスを外に出しておかないと、保存を押したのに、何もダウンロードされていないということになるので注意。

var fileRef:FileReference = new FileReference();
private function download(event:Event):void {
fileRef.download(new URLRequest(dl_base + event.target.label));
}

●mailto
あと、メーラーの起動は以下のようにして、html上のmailtoと同じようにできる。

navigateToURL(new URLRequest(mailto.label + "?subject=exblog2fc2blog引越ツール:"),"_self");



開発生産性の高いものというのは、得てして痒いところに手が届かないもので、というかちょっとサンプルと違うバリエーションをやるだけでいろいろと調査と試行錯誤が必要になる。
簡単なものを作る分には生産性が高いといえるが、ちょっと凝ったものを作る場合、トータルで見て本当に生産性が高いのかは疑わしい。

関連記事
スポンサーサイト

テーマ : インターネットサービス
ジャンル : コンピュータ

コメント

非公開コメント

プロフィール

dayan

Author:dayan
小職は、SE(システムエンジニア)を専門としておりますが、技術的な情報を中心に、それ以外に経済関連の日記、たわいもない日記も載せていきます。
[公式HPもよろしく!]

天気予報

-天気予報コム- -FC2-
リンク
ブロとも申請フォーム

この人とブロともになる

カテゴリー
最近の記事
ブログ内検索
最近のコメント
最近のトラックバック
RSSフィード
月別アーカイブ


上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。