
私にはこの Web サイトがあります。ユーザーがフォームを送信すると、Python スクリプトが PHP ページを通じて実行され、Python スクリプトによって zip ファイルが作成され、リンクを通じてダウンロードできるようにユーザーに提供されます。ファイルは巨大になる可能性があります (数 GB)。
私は大学のサーバーで作業しているので、そのサーバーのルールと機能に厳密に従わなければなりません。問題は次のとおりです。
この Web サイトは に保存されています/data/mywebsite
が、ディスク容量が限られています。もちろん、この Webサイトwww-data
は Apache サーバーから主にアクセスできるため、 が所有しています。
に 1 TB のストレージが提供されていますが/experimentdata/
、これは という特定の 1 人のユーザーのみがアクセスできますtheuser
。これは、このフォルダーが 1 人の特定のユーザー ID でアクセスできる samba マウントであるためです。
にファイルを作成するには、ユーザー としてファイルを作成するコマンドを/experimentdata
使用します。ここで問題となるのは、このファイルを Apache 経由でダウンロードするためのリンクで提供するにはどうすればよいですか?sudo -u theuser
/experimentdata/downloadme.zip
theuser
たとえば、 に置いたシンボリック リンクを使用することを考えました/data/mywebsite/download/downloadme.zip
。その問題は、ユーザーにwww-data
ファイルを読み取る権限がまったくないことです。
/experimentdata/downloadme.zip
ユーザーがユーザーをwww-data
介してファイルをダウンロードできるようにするにはどうすればよいでしょうかtheuser
?
関与することはまったく問題ないと明確に言いたいのですsudo -u theuser
が、そこから自分の Web サイト フォルダー外のどこかへのリンクを作成する方法がわかりません。
追伸: 追加情報が必要な場合はお問い合わせください。
答え1
やるべきことは、 の代わりにphp
/ がpython
直接データを返すようにすることだと思いますapache
。コードでは、 が行うのと同じことを行うことができますapache
。私の経験では、これは別のディレクトリを開いたり、 を使用したりsudo
、 のファイル権限を変更したりするよりもはるかに優れていますapache
。
プログラムがインターネット接続よりも速く大きなファイルを生成する場合は、プログラムから直接データをストリーミングできます。これにより、余分なデータ ファイルとそれを管理するためのコード、およびそれを記憶するためのメカニズムが不要になります。
Stack Overflow のこの回答では、コードが でどのように機能するかを示していますphp
。https://stackoverflow.com/a/4357904/5484716。
このように呼び出されるプログラムの場合、すべてのstderr
ストリーム出力を削除し、Python プロセスからの戻りコードがプロセスの成功または失敗を正確に反映していることを確認します。
以下の例は、popen()
stackoverflow の上記の例のシナリオで使用する呼び出しを示しています。 をシェル コマンドの前に追加しました。これにより、 と の両方にデータが来るとでデッドロックの原因になる可能性があるexec 2>/dev/null;
ため、シェル自体からでも標準エラーに出力が送られないことが保証されます。stderr
stdout
popen()
ディスク ファイルをユーザーにダウンロードする場合:
$fp = popen('exec 2>/dev/null; sudo -u theuser cat yourfile.zip', 'r');
アクティブなプロセスからデータをダウンロードする場合:
$fp = popen('exec 2>/dev/null; sudo yourpythonscript arg argN', 'r');
これらのコマンドラインはシェルコマンドであり、シェルのメタ文字に対して適切に引用符で囲む必要があります。
2 番目の方法では、サーバーはすぐにデータの送信を開始します。ユーザーがフォームを正常に送信すると、すぐにブラウザに「名前を付けて保存」ダイアログが表示されます。ユーザーが出力ファイルを選択すると、php
スクリプトはデータを直接ネットワーク経由でリモート ファイルに転送します。
スクリプトはpython
次のように印刷されますのみ標準出力に zip データを出力し、 zip プロセスの成功または失敗を正確に表す終了コードを返します。python
スクリプトではsys.stdout
、たとえばに出力を書き込む必要がありますzf = ZipFile(sys.stdout, ...
。
pclose()
呼び出して戻り値を確認することは重要ですなぜなら、それが zip が成功したかどうかを知る唯一の方法だからです。 がpclose()
0 以外を返す場合、何かが間違っています。
クライアントによるファイルの処理方法は、以下の設定response headers
などによって異なります: content-type:
、content-encoding:
、content-disposition:
参照:http://www.w3.org/Protocols/rfc2616/rfc2616-sec6.html、response-header
およびentity-header
情報を参照してください。