このページは福井県立大学の田中求之が2006年1月まで運用していた Mac のサーバ運用に関する会議室 「Web Scripter's Meeting」の記録です。情報が古くなっている可能性がありますのでご注意ください。

フォームで入力した内容をPDFにして送り返す

発言者:川原良一
( Date Wednesday, December 24, 1997 13:48:36 )


フォームの入力内容やファイルメーカーの検索結果を、PDFファイルに
して送り返す、ということをCGIでやってみたのですが、2つほどわか
らない点があります。

・1つめは、
PDFファイルの作成時の問題で、ダイアログなしでPDFWriterから印刷
(ファイルの作成)をしたときのファイル名と保存先の指定の仕方です。
ApplescriptのCGIから、ファイルメーカーに、ファイルメーカーのスクリ
プト実行で、ダイアログなしの設定で印刷をさせているのですが、名称未
設定のファイル名のファイルがデスクトップに作成されてしまいます。

CGIから(あるいはファイルメーカーから)ファイル名と保存先の指定はで
きないのでしょうか?


・2つめは
複数ユーザーの同時アクセスの場合の問題で、

現在の処理手順:

フォーム入力−>入力内容のTango.acgiによるファイルメーカーファイルへ
の挿入−>Applescript cgi処理[レコードの選択(レコードIDと”Tangoが
発行するUSERREFFERENCE+挿入処理が行われた時間”をキーにした検索)−>
印刷−>ファイル”名称未設定”のファイル名の変更とデスクトップから保
存フォルダーへの移動−>リダイレクトによるファイルの指定]

で、例えば、他人の入力結果を受け取る、ということが起きる可能性はあるの
でしょうか?ということです。

ごちゃごちゃして申し訳ありませんが、
以上について教えていただきたいのですが。
よろしくお願いいたします。

以下のアドレスに、とりあえず作ってみたものがあります。

→  テスト

重松修 さんからのコメント
( Wednesday, December 24, 1997 16:56:54 )

>>複数ユーザーの同時アクセスの場合の問題で

これはいつもついて回る問題ですよね。

結論から言えば、Tango.acgiは知りませんが、AppleScriptはスレッド処理を
しないそうなので、あまり深く考えなくても良いのではと思うんですが、
以前田中先生が興味深いことをおっしゃっていたのが気になります。

というのは、アクセスが集中したときには、通常は先のリクエストから先に結果が
Repleyされるはずなのに、そうでない場合があると言うのです。通常は、受け取った
処理を完了するまでその処理に専念すれば、そういう事は絶対にないはずなんです
けど、内部的にはある一定時間ごとに割り込みを発生させてイベントをハンドル
しているのかも知れません。そうすると、一定時間を過ぎると、前の処理は
一旦打ち切られそのまま次の処理を開始してしまうって事になりますね。
一応タイムアウトしなかった場合には、後の処理の結果の後に、前の処理の結果
が返されるようになりますね。

自分はアクロバットを持っていませんので、どれくらい変換にかかるかわかりま
せんが、(1) の問題を解決してファイル名を例えば、シリアルやタイムスタンプ
にして、CGIの処理を検索結果をPDFにして、特定の名前で、特定のフォルダに
しまい、その後、その名前を引き数に持たせて、PDFを送りだすCGIにリダイレクト
すれば良いと思います。PDFはだんだんたまりますので、10分置きくらいに自動で
最終更新から一定時間が過ぎたものをすてるようにしたら良いと思います。

川原良一 さんからのコメント
( Wednesday, December 24, 1997 18:10:09 )

どうもありがとうございます。

基本的なことを理解していないのだと思うのですが、
AppleScriptのCGIで、ファイルの作成>ファイル名変更>移動>リダイレクト
指定、の一連の作業を行わせているので、その間、サーバー(Webstar)は待っ
ている(Tango.acgiなどの処理も行われない)ということでいいのでしょうか。
あと、印刷の処理は、ファイルメーカーが行いますが、CGIからの命令なので、
その間にサーバーが他のことをすることはない、ということでいいのでしょう
か?

>というのは、アクセスが集中したときには、通常は先のリクエストから先
>に結果がRepleyされるはずなのに、そうでない場合があると言うのです。

実際には、2人の同時アクセスすら可能性が低いと思うのですが(^_^;、
やはり心配です、というか、そうしてはいけない責任があると思うのですが、
そういう事態を防ぐためには、どのような工夫があるのでしょうか?

????ばかりで申し訳ありません。

あと、もっと根本的に、処理事態がうまくいかない場合があるようで、
先ほど2回、エラーが出ていました(自分ではうまくいっていても、
難しいですね)。
いちおう直したのですが、もし時間に余裕がある方は、試していただけ
ませんでしょうか。よろしくお願いいたします。


→  テスト

田中求之 さんからのコメント
( Wednesday, December 24, 1997 20:32:53 )

>AppleScriptのCGIで、ファイルの作成>ファイル名変更>移動>リダイレクト
>指定、の一連の作業を行わせているので、その間、サーバー(Webstar)は待っ
>ている(Tango.acgiなどの処理も行われない)ということでいいのでしょうか。

CGI は基本的に LIFO、つまり、後からきたメッセージが割り込みで先に処理される
という仕様になっています。これは AS で再帰呼び出しなどを可能にする(re-entrancy
を確保する)ためです。

このため、長い処理を行っている最中に、別の人が同じ CGI を呼び出すと、前の処理が
中断されて、後の方が処理されます。

このため、テンポラリファイルに同じ名前を使っていたり(あるいは「名称未設定」を
使っていたり)、グローバル変数を書き換える処理などがあると、一発でエラーになり
ます。

ですから、PDF を作成する際に、ファイル名を、他との重複がまず起きないような
ファイル名を割り当てて作成しておく必要があります。また、処理に時間がかかる
ようなときには、タイムアウトが起きないように工夫する必要があります。

PDF にファイル名を指定する方法については、今はちょっと調べている暇がないので
(FMP4, Acrobat 共に持っていますが)、他の方、フォローをお願いします。

木下@キー・プランニング さんからのコメント
( Wednesday, December 24, 1997 22:10:22 )

>ApplescriptのCGIから、ファイルメーカーに、ファイルメーカーのスクリ
>プト実行で、ダイアログなしの設定で印刷をさせているのですが、名称未
>設定のファイル名のファイルがデスクトップに作成されてしまいます。
>
>CGIから(あるいはファイルメーカーから)ファイル名と保存先の指定はで
>きないのでしょうか?

ファイルメーカーのスクリプトでは、スクリプトを作成した直前に行った
内容を記憶しているので、御希望の設定を一度手動で行ってからスクリプ
トを記憶させ直すと良いでしょう。ただし、これだと毎回同じ処理の繰り
返しでランダムな処理はできないので、ランダムな処理が必要な場合は、
Applescriptを連携させる必要があります(保存後ファイル名を変更させる
とか)。

川原良一 さんからのコメント
( Thursday, December 25, 1997 11:21:41 )

ありがとうございます。

>ですから、PDF を作成する際に、ファイル名を、他との重複がまず起きないような
>ファイル名を割り当てて作成しておく必要があります。また、処理に時間がかかる
>ようなときには、タイムアウトが起きないように工夫する必要があります。

変更後のファイル名は”その時点でのユーザー固有の値+タイムスタンプ”なので、
重複は起きないと思うのですが、いまのところどうしても名称未設定のファイルを
一度作成しないといけない状態です。

”タイムアウトが起きないように”というのは、CGIのスクリプトになにか入れると
よいのでしょうか?


>ファイルメーカーのスクリプトでは、スクリプトを作成した直前に行った
>内容を記憶しているので、御希望の設定を一度手動で行ってからスクリプ
>トを記憶させ直すと良いでしょう。

やってみたのですが、やはり名称未設定になってしまいます。
ダイアログを出して、ファイル名を指定して印刷後、
再度ダイアログを表示させる場合では、前回のファイル名がそのまま入っ
ていますが、ダイアログなしの場合だと、名称未設定になってしまう
のですが・・・


あと、何人かの方にアクセスしていただいたようです。ありがとうございます。
タイムスタンプの書式指定(Tango.acgiでのシステムグローバル変数の変更)
が、途中でもとに戻ってしまうことがときどきあって、そのため、CGIでの
ファイル名の変更ができず、エラーが起きる場合があるようです。
いちおうシステムグローバル変数を変更する場所をかえてみました。






木下@キー・プランニング さんからのコメント
( Thursday, December 25, 1997 13:18:57 )

>>ファイルメーカーのスクリプトでは、スクリプトを作成した直前に行った
>>内容を記憶しているので、御希望の設定を一度手動で行ってからスクリプ
>>トを記憶させ直すと良いでしょう。
>
>やってみたのですが、やはり名称未設定になってしまいます。

私はAcrobatをもっていないので、固有の問題かも知れませんが、スクリプトを
記憶させ直す時に出てくるダイヤログで、「置き換え」ラジオボタンをチェック
していますか?
これを忘れると、以前の条件のままのスクリプトになってしまいます。多分、
「そんなこと分かってる」でしょうが、念のため。

田中求之 さんからのコメント
( Thursday, December 25, 1997 14:56:43 )

>”タイムアウトが起きないように”というのは、CGIのスクリプトになにか入れると
>よいのでしょうか?

CGI の処理をなるべく早くする(FMP をフロントに持ってくる等)以外のことでしたら
サーバー側のタイムアウトの時間を長めに設定するというのが基本です。

スクリプトの側で対処するときには、send partial を使って処理の経過を
メッセージで返すなどの方法が可能ではありますが、スクリプトを根本的に
作り替える必要があるのと、うまくやらないとかえって煩雑なだけで効果が
ないということになりますので、あまりお勧めしません。

川原良一 さんからのコメント
( Thursday, December 25, 1997 15:38:19 )

>CGI の処理をなるべく早くする(FMP をフロントに持ってくる等)以外のことでしたら
>サーバー側のタイムアウトの時間を長めに設定するというのが基本です。

タイムアウト設定はいじっていなかったので、最大値に変更しようと思い
ます。



>記憶させ直す時に出てくるダイヤログで、「置き換え」ラジオボタンをチェック
>していますか?

ぜんぜん分かっていないのですが(^_^;どこで出てくるのですか?

木下@キー・プランニング さんからのコメント
( Thursday, December 25, 1997 17:08:15 )

>ぜんぜん分かっていないのですが(^_^;どこで出てくるのですか?

手動で記憶させたい作業を一度行う。→記憶させたいスクリプト定義の編集ダイヤログを
開いて(何もしないで)ふたたび閉じる。【ここでそのダイヤログが出る】

「このスクリプトを更新するために、次の情報が必要です...云々...」と出て、その下に
条件を更新するか、維持するかのリストが出るので、この場合は全部「置き換え」を
チェックして、OKボタンをクリック、です。

AcrobatでPDF文書を保存するのが、通常の印刷と全く同じ仕組みなら、これで上手く
いくと思うのですが、Acrobat独自の部分があるとどうなるかは不明です。(^_^)

決まったディレクトリに特定のファイル名で保存されれば、AppleScriptで加工する
時も楽ですからね。

前田隆博 さんからのコメント
( Thursday, December 25, 1997 17:46:40 )

私の手元の環境でTangoを利用した方法に関してテストしたところ,以下のようになりました。

1.Demo Cars に印刷のファイルメーカースクリプトを「ダイアログなし」で作成
2.Tangoで通常の検索動作の後ろに続けて直接DBMSアクセスを追加し,印刷スクリプト実行を指定
3.Tangoのクエリードキュメントに対して検索を実行し,印刷実施
4.デスクトップ上に「名称未設定」PDFファイルが出現

次にファイルメーカースクリプトを印刷ダイアログなしのチェックを外してみると,PDFを出力
する際のダイアログボックスが出ます。OKを押すとファイルメーカーデータベースファイルと
同じフォルダに「Demo Cars.pdf」というPDFファイルを出力しようとします。

この現象から考えるとダイアログ無しではPDF Writerに必要な情報が渡されないまま出力される
ためにデスクトップへ名称未設定で出力されているようです。
また,ファイルメーカーからの印刷スクリプトにおいてもPDF出力を考慮した設定が無いため
対応が難しいと思われます。

強引な方法としては,Tangoでデスクトップに名称未設定を出力後,続けてAppleScriptを起動して
ファイル名の変更と該当するWebサーバディレクトリへ移動させるというのはいかがでしょうか?
AppleScriptに関する知識が無いためサンプルは作成できませんが,これであれば実現可能かと
思われます(PDFが出来上がるタイミングとAppleScriptがそのファイルを見つけるまでに時間差が
あるとコントロールが難しいかもしれません)。

同時処理の問題に関してはTangoからファイルメーカー続けて71レコード全部と1レコードだけの
印刷を行う検索を実行したところ71レコードの印刷をせずに1レコードの印刷を続けて2回実施
いたしました。
この事からファイルメーカーProがPDF Writerにデータを渡し終わるまではファイルメーカーに
処理をさせては駄目なようです。
対応としてはグローバル変数とフラグを管理するためのデータベースを用意して同時に複数の
人間が印刷を実行しないようにコントロールをすることが出来ると思います。

推測だけで申し訳ありませんが,お役に立てれば幸いです。


川原良一 さんからのコメント
( Friday, December 26, 1997 11:01:40 )

どうもいろいろありがとうございます。

>「このスクリプトを更新するために、次の情報が必要です...云々...」と出て、その下に
>条件を更新するか、維持するかのリストが出るので、この場合は全部「置き換え」を
これ、出せました(^_^) ただ、印刷のFMスクリプトのみでは出てこなくて、
用紙設定スクリプトを組み込んだ場合のようです。
結局、前田さんが指摘されているようなことで、ファイル名と保存先指定はできないという
結論になるのでしょうか?

もう一つだけ教えていただきたいのですが(少し表題の内容からそれますが)、
現在は、フォームの内容のFMへの挿入まではTango.acgiで行って、その後、
(A)Applescript.cgiを直接呼び出して、その中で、(1)FMに印刷したいレコードの検索
と印刷をさせる(印刷はdo script)、と(2)ファイル名の変更と移動、リダイレクト指定
を行わせています。
それで、これと同じことは、
(B)Tango.acgiのクエリードキュメントに、検索、DBMS直接アクセス(印刷スクリプト指定)、
外部命令(Applescript呼び出しで(2)を行わせる)、を記述しても、
(C)FMスクリプトに印刷とApplescript実行((2)を行わせる)を記述して、Tango.acgiの
クエリードキュメントから呼び出すか、直接Applescript.cgiから呼び出す、
でもできそうなのですが、
同時アクセスの問題からみた場合、これらは全て同じなのでしょうか?
勉強不足なのだと思いますが、混乱しています。
的外れな変な質問かもしれませんが、どなたかよろしくお願いいたします。

前田隆博 さんからのコメント
( Wednesday, January 07, 1998 19:17:59 )

私にはA,B,Cのケースに関してテスト環境を用意する事が
出来ないため、残念ながら正確なコメントをする事が出来ません。

いずれの場合でもFM側では同時に処理をすることは出来ませんので、
FMにアクセスしているアプリケーション側で制御する必要がある
と思います。

考えられる注意点
Aの場合、この場合は他のB,Cにも共通した点について注意する必要があります。
同時利用をした際にApplescript.cgiが処理中にTangoが同じ
データベースに挿入を実行した場合に不具合が生じないか確認する必要があります。
また、2人目の人の印刷物の名称が「名称未設定1」にならないように
印刷後ファイル名を変更するまでにFMが次の印刷を終了しないかも注意が必要です。

Bの場合は各動作の間に他の人の要求が実行された際に割り込まれる可能性がある
ため、一連の動作を特定の利用者のみが利用できるように制限する必要があります。

Cの場合もTangoを利用して検索後に印刷の命令を出すため、Bと同じ
配慮をする必要があります。


私は一連の流れに対して同時利用出来なくする方が良いと思います。


川原良一 さんからのコメント
( Thursday, January 08, 1998 13:19:27 )

どうもありがとうございました。

何も工夫をしない場合は(そもそも工夫の仕方が分からない・・・)、
B、CよりはAの方がいい、ということですね。
Aの場合に関してご指摘いただいた点については、確認してみます。


ファイル作成関連の一連の処理開始と同時に、WEBSTARが他の接続を
受け付けなくなるようにする、というのもいいような気もするのですが、
その時だけそういう設定に変更して、処理後は元に戻す、などということ
は可能なのでしょうか?(また?がついてしまいました(^_^;)



田中求之 さんからのコメント
( Thursday, January 08, 1998 15:36:12 )

>ファイル作成関連の一連の処理開始と同時に、WEBSTARが他の接続を
>受け付けなくなるようにする、というのもいいような気もするのですが、

CGI の拡張子を .cgi にしておく(.acgi ではなく)と、CGI の処理中は他のアク
セスの処理が一切行われないことになっていますので、これを利用するという手はあり
ます。

川原良一 さんからのコメント
( Friday, January 09, 1998 12:37:33 )

ということは、FMへの挿入処理も含めて、一連の処理を、1つの
Applescript CGIにしてしまえば、Tango.acgiの割り込みとか考
えなくて済むので、他人の挿入結果が印刷されたり、”名称未設定1”
ができたりする心配はなくなる、ということですね。(?)
(FMへの挿入処理のApplescriptを記述するのが大変そうですが)

前田隆博 さんからのコメント
( Friday, January 09, 1998 14:08:55 )

>一連の処理を、1つのApplescript CGIにしてしまえば、Tango.acgiの
>割り込みとか考えなくて済む

この場合、対象とするファイルメーカーデータベースファイルは.cgiの
Applescript CGIだけが使用することが前提になります。
同じデータベースファイルに対してTangoから検索するシステムを
作ってしまうとWebSTARはTangoに対して要求を出してしまいますので
同時処理の時に不具合が生じないか検証する必要が出てきます。

>(そもそも工夫の仕方が分からない・・・)
これはグローバル変数を利用して特定のグローバル変数を持っている人だけが
印刷するファイルメーカーデータベースファイルへアクセスできるように
する方法が考えられます。
サンプルの中の売ります買いますのlogin.qryのユーザー認証が参考に
なるかと思います。

グローバル変数の扱いが難しいときは内田洋行のTangoサポート窓口が
1月末日までは無償ですので、一度相談されてはいかがでしょうか?


川原良一 さんからのコメント
( Tuesday, January 27, 1998 11:35:38 )

ありがとうございます。
コメントするのが遅くなって申し訳ありません。

Tangoのグローバル変数の扱いは、マニュアルだけだと今ひとつわからない
のですが、どう質問していいかもわからないので(^_^;、今勉強しています。
(たぶん無償期間中にはどうにもならないと思い、かつ利用せざるおえない
のでサポートの申し込みはしました)

ところで、今回の件では、やはり、PDFWriterの出力ファイル名を直接
いじるのが一つの大きなカギだと思い、あきらめきれずにいろいろ調べていた
のですが、とりあえず、ファイル名の変更方法がわかりました。
PDFWriterのSTR#リソースのID -8191の2)がファイル名”名称未設定”でした。
これをTanaka's osax1.2(心から感謝いたします!!)のwriteToIndStrRsrc
で書き換えてから印刷させると、デスクトップにその名前でファイルが作成さ
れました。
できれば保存先も何とかしたいところですが、これだけでもかなり扱いやすく
なったような気がします。

田中求之 さんからのコメント
( Tuesday, January 27, 1998 12:58:44 )

>PDFWriterのSTR#リソースのID -8191の2)がファイル名”名称未設定”でした。
>これをTanaka's osax1.2(心から感謝いたします!!)のwriteToIndStrRsrc
>で書き換えてから印刷させると、デスクトップにその名前でファイルが作成さ
>れました。

なかなか強引な技を使いますねぇ(笑)