2009-11-22 133 views
11

我正在編寫一個反向腳本下載腳本,而且我的計劃是創建一個臨時文件,它以會話ID命名,然後會話過期後,文件將自動刪除。可能嗎 ?你能給我一些提示如何在PHP中做到這一點?創建臨時文件並自動刪除

感謝這麼多的任何答覆

+0

該文件應保存多久? – Ikke 2009-11-22 16:43:29

+0

您能否更具體地瞭解您想要實現的目標?反吮吸DL腳本有點模糊。什麼是腳本試圖解決的UseCase或問題? – Gordon 2009-11-22 17:13:41

+0

Hi lkke, 我只想讓用戶只在他/她的會話中下載,就像他不能簡單地複製和粘貼鏈接給其他人 嗨Gordon, 我想強制用戶從他/她的會話下載文件我的網站,控制速度。因此,我認爲要在HTTP文檔的臨時目錄中創建臨時文件,以便用戶可以下載它們,然後在會話過期後自動刪除它們( – mrblue 2009-11-22 19:30:59

回答

9

所以我們有一個或多個文件可供下載。爲每個下載請求創建臨時文件不是一個好主意。爲每個文件創建一個symlink()反而是一個更好的主意。這將節省磁盤空間的負載並降低服務器負載。

在用戶會話之後命名符號鏈接是個不錯的主意。更好的辦法是生成一個與會話相關聯的隨機符號鏈接名稱&,以便該腳本可以處理每個會話的多個下載。您可以使用session_set_save_handler()link)並註冊一個自定義的read函數,用於檢查過期的會話並在會話過期時刪除符號鏈接。

+1

嗨pygorex1, 這正是我所期待的。非常感謝。 – mrblue 2009-11-25 16:53:17

+0

唯一的問題是,符號鏈接在php版本5.2上不起作用 – coderama 2011-09-20 15:41:36

+0

鏈接現在是404,只是拼了你,以便你可以修復它 – 2014-02-20 12:54:32

8

PHP有該名稱tmpfile的功能。它創建一個臨時文件並返回一個資源。該資源可以像任何其他資源一樣使用。

E.g.手冊中的示例:

<?php 
$temp = tmpfile(); 
fwrite($temp, "writing to tempfile"); 
fseek($temp, 0); 
echo fread($temp, 1024); 
fclose($temp); // this removes the file 
?> 

當關閉(使用fclose())或腳本結束時,文件會自動刪除。您可以在資源上使用任何文件功能。你可以找到這些here。希望對你有幫助?

另一種解決方案是以常規方式創建文件,並使用cronjob定期檢查會話是否過期。到期日期和其他會話數據可以存儲在數據庫中。使用該腳本查詢該數據並確定會話是否過期。如果是這樣,請從磁盤上物理刪除它。確保每小時運行一次腳本(取決於您的超時時間)。

+0

我不認爲這對mrblue的問題的解決方案導致當會話過期的文件是在腳本結束/ FCLOSE(),而不是刪除。 – 2009-11-22 16:52:45

+0

你說得對,我想。必須一直在閱讀那部分。在我的文章中添加了更多信息。現在取決於他;) – TheGrandWazoo 2009-11-22 17:02:54

+0

嗨TheGrandWazoo,謝謝你的回答。 我曾想過這種解決辦法,但如果網站可擴展至和Philippe是正確的它不可能是可能的,因爲腳趾的性能問題,我關心的是,PHP支持「鉤子」功能,如會話過期或後自動調用開始。 – mrblue 2009-11-22 19:33:18

2

我建議你不要在第一個地方複製文件。我會執行以下操作:當用戶請求文件時,您將生成一個隨機唯一字符串,以這種方式給他鏈接:dl.php?k=hd8DcjCjdCkk123然後將該字符串放到數據庫中,存儲他的IP地址,可能會話和您生成的時間鏈接。然後另一個用戶請求該文件,確保所有的東西(哈希,IP等)匹配,並且鏈接沒有過期(例如,自上一代以來不超過N小時),如果一切正常,則使用PHP管道文件。設置一個cron作業來查看數據庫並刪除已過期的條目。你怎麼看?

tmpfile

創建一個臨時文件在讀寫唯一的 名(W +)模式和 返回一個文件句柄。該文件是 在關閉時自動刪除 (使用fclose()),或者當腳本 結束時。

+0

我不認爲這對mrblue的問題的解決方案導致當會話過期的文件是在腳本結束/ FCLOSE(),而不是刪除。 – 2009-11-22 16:52:10

+0

嗨roddik, 菲利普是正確的,我想過這個問題的解決方案,但它並不適用於我的情況下尤其是性能問題 – mrblue 2009-11-22 19:36:31

3

你能解釋一下你的問題嗎?因爲我沒有看到爲什麼不使用$_SESSION$_SESSION中的數據存儲在服務器端的文件中(參見http://php.net/session.save-path)。至少默認情況下。 ;-)

+0

嗨菲利普, 是的,我真的想用戶$ _SESSION(其實我所做的那樣),但我找不到任何關於某些內容的文檔或主題,例如「hook」動作,例如:我們可以創建一個函數,在會話過期或啓動後自動調用該函數。這是我的想法和關切。 感謝您的時間 – mrblue 2009-11-22 19:34:52

+0

走另一條路。新會話創建時(例如,$ _SESSION爲空並且您之前填充了該會話)作出反應,而不是會話過期。問題是,會話可能會過期而無需用戶採取任何行動(會話過期並被垃圾收集器刪除)。你想要做什麼? – 2009-11-22 20:35:06

2

好了,我們有以下幾點要求爲止

  1. 讓他/她的會話的用戶只下載
  2. 沒有複製粘貼&鏈接到別人
  3. 用戶有從網站下載,例如沒有盜鏈
  4. 控制速度

讓我們來看看。這不工作密碼,但它應該沿着這些路線工作:

<?php // download.php 

session_start(); // start or resume a session 

// always sanitize user input 
$fileId = filter_input(INPUT_GET, 'fileId', FILTER_SANITIZE_NUMBER_INT); 
$token = filter_input(INPUT_GET, 'token', FILTER_UNSAFE_RAW); 
$referer = filter_input(INPUT_SERVER, 'HTTP_REFERER', FILTER_SANITIZE_URL); 
$script = filter_input(INPUT_SERVER, 'SCRIPT_NAME', FILTER_SANITIZE_URL); 

// mush session_id and fileId into an access token 
$secret  = 'i can haz salt?'; 
$expectedToken = md5($secret . session_id() . $fileId); 

// check if request came from download.php and has the valid access token 
if(($expectedToken === $token) && ($referer === $script)) { 
    $file = realpath('path/to/files/' . $fileId . '.zip'); 
    if(is_readable($file)) { 
     session_destroy(); // optional 
     header(/* stuff */); 
     fpassthru($file); 
     exit; 
    } 
} 
// if no file was sent, send the page with the download link. 
?> 
<html ... 

<?php printf('a href="/download.php?fileId=%s&amp;token=%s', 
       $fileId, $expectedToken); ?> 

... 
</html> 

就是這樣。沒有數據庫要求。這應該包括要求1-3。您無法使用PHP控制速度,但是如果您在發送文件後不破壞會話,則可以爲會話編寫計數器並限制用戶在會話期間發送的文件數。

我完全同意這可以比這個monkeyform hack更加優雅地解決,但作爲概念驗證,它應該是足夠的。

+0

嗨Gordon, 這差不多是我寫在代碼中的東西的90%,但是你的令牌更安全。非常讚賞這一點。 – mrblue 2009-11-25 16:52:16

+0

令牌增加了安全性,但它也使得您不必符號鏈接或複製您的文件了,因爲該令牌對會話+文件是唯一的。令牌基本上是pygorex1爲符號鏈接名稱創建的。而不是從它創建一個符號鏈接,然後您將不得不以某種方式刪除它,只需將名稱/標記與常規fileId一起發送即可。減少維護。 – Gordon 2009-11-25 19:36:44

0

也許這是遲到回答,但我試圖分享功能googlize!

,如果你使用的cPanel有對託管文件阻止外部 請求一個短而快速的方法,其名稱爲:盜鏈

你可以啓用你的Cpanel的HotLinks,並確保沒有人可以請求你的文件從另一個託管或使用你的文件作爲下載參考。

0

爲了實現這一目標,我將創建一個文件並使用chmod保護它 - 使其不可用於公衆。或者,也可以將內容保存在數據庫表格行中,隨時提取。

使其可下載爲文件。爲此,我會從受保護的文件中獲取內容,或者如果它存儲在數據庫表中,則獲取它並僅輸出它。使用php頭文件,我會給它一個所需的名稱,擴展名,指定它的類型,並最終強制瀏覽器將輸出下載爲固定文件。

這樣,您只需將數據保存在受保護的文件或數據庫中的一處。強制客戶端瀏覽器根據條件符合的次數下載它,例如,只要用戶已登錄等等。無需擔心磁盤空間,製作任何臨時文件,cronJobs和或自動刪除文件。