
我有這個網站,如果用戶提交表單,則透過 php 頁面執行 python 腳本,並且 python 腳本創建一個 zip 檔案並應將其提供給用戶透過鏈接下載。該檔案可能很大(幾 GB)。
由於我在大學伺服器上工作,因此我嚴格遵守他們的伺服器規則和功能。問題是這樣的:
該網站儲存在/data/mywebsite
,其磁碟空間有限。當然,這是由我擁有的,www-data
因為它主要由我的 Apache 伺服器存取。
我在 中獲得了 1 TB 儲存空間/experimentdata/
,只能由單一特定使用者(例如 )存取theuser
。這是因為該資料夾是 samba 掛載,可由單一特定使用者 ID 存取。
為了在中建立文件/experimentdata
,我使用一個命令以使用者身分sudo -u theuser
建立文件。現在我的問題是:如何透過 Apache 下載連結提供此文件?/experimentdata/downloadme.zip
theuser
我想到使用我放入的符號鏈接,例如/data/mywebsite/download/downloadme.zip
.問題是用戶www-data
絕對沒有讀取該檔案的權限!
怎麼樣才能讓用戶透過用戶/experimentdata/downloadme.zip
跟用戶一起下載檔案呢?www-data
theuser
我想明確地說,參與sudo -u theuser
是絕對可以的。但我不知道如何將其連結到我的網站資料夾之外的某個位置。
PS:如果您需要任何其他信息,請詢問。
答案1
我認為要做的就是讓php
/python
直接返回數據而不是apache
.您的程式碼可以做同樣的事情apache
。根據我的經驗,這比打開另一個目錄和/或使用sudo
或更改 的檔案權限apache
等要好得多。
如果程式產生大檔案的速度比網路連線的速度快,那麼您可以直接從程式串流數據,從而消除額外的資料檔案和管理它的程式碼以及記住它的機制。
Stack Overflow 上的這個答案展示了程式碼如何在php
.https://stackoverflow.com/a/4357904/5484716。
對於以這種方式呼叫的程序,請消除所有stderr
流輸出,並確保 python 進程的回傳程式碼準確反映進程的成功或失敗。
下面的範例顯示了popen()
您在上面的 stackoverflow 範例場景中將使用的呼叫。我已添加exec 2>/dev/null;
到 shell 命令前面。這可以確保不會有任何輸出進入標準錯誤,即使是來自 shell 本身,因為資料同時來自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');
這些命令列是shell 指令,並且需要為 shell 元字元適當地引用。
在第二種方法中,伺服器將立即開始發送資料。當使用者成功提交表單後,他們會立即從瀏覽器中看到「另存為」對話方塊。一旦使用者選擇輸出文件,您的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
資訊。