2014-02-19 129 views
5

我提供這樣的用PHP一個zip文件下載:提供一個遠程文件下載

header("Content-Type: application/zip"); 
header("Content-Disposition: attachment; filename=\"".$filename."\""); 
header('Content-Description: File Transfer'); 
header('Content-Transfer-Encoding: binary'); 
header('Expires: 0'); 
header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); 
header('Pragma: public'); 
header('Content-Length: '.filesize($location)); 

readfile($location); 

我如何處理,當該文件位於像S3或Dropbox的(在這裏我有一個遠程服務器上權利當然)

我不喜歡任何重定向導致用戶不應該看到原來的位置。

我是否必須下載該文件並(臨時)將其存儲在服務器上?

+0

定義「商店」。如果您的訪問者的瀏覽器和CDN之間的直接連接不可取,那麼您的服務器顯然必須充當代理,但您可以根據需要多次下載它。 –

+0

如果用戶點擊http://server1.com/file.zip(s)鏈接,他不應該注意到該文件實際上位於http://server2.com/file.zip – Xaver

+0

您可以閱讀從一個流發送到另一個流,但然後您的服務器仍然需要下載整個文件 - 只是不要將它存儲在任何地方。如果你想排除這部分,我想,重定向是唯一的選擇。 – raina77ow

回答

2

你可以(也可能是應該!)在本地存儲文件,但你不要來。

所以這裏有幾個可能的解決方案。這些示例假設$文件名或者已被安全地產生或已消毒的東西,如:

$filename = preg_replace('/[^\w.]/', '', $filename); //sanitize 

1)ReadFile的,用了allow_url_fopen啓用: (見http://www.php.net/manual/en/features.remote-files.php進一步的細節)

readfile("http://url/to/your/$filename"); 

2 )更多的東西cacheingy,如:

// Serve a file from a remote server. 
function serveFile($filename) { 
    // Folder to locally cache files. Ensure your php user has write access. 
    $cacheFolder = '/path/to/some/cache/folder'; 
    // URL to the folder you'll be downloading from. 
    $remoteHost = 'http://remote.host/path/to/folder/'; 

    $cachedFile = "$cacheFolder$filename"; 

    // Cache the file if we haven't already. 
    if (!file_exists($cachedFile)) { 
     // May want to test these two calls, and log failures. 
     file_put_contents($cachedFile, file_get_contents("$remoteHost$filename")); 
    } 
    else { 
     // Set the last accessed time. 
     touch($cachedFile); 
    } 
    readfile($cachedFile) or die ("Well, shoot"); 

    // Optionally, clear old files from the cache. 
    clearOldFiles($cacheFolder); 
} 

// Clear old files from cache folder, based on last mtime. 
// Could also clear depending on space used, etc. 
function clearOldFiles($cacheFolder) { 
    $maxTime = 60 * 60 * 24; // 1 day: use whatever works best. 
    if ($handle = opendir($cacheFolder)) { 
     while (false !== ($file = readdir($handle))) { 
      if ((time() - filemtime($path.$file)) > $maxTime) { 
       unlink($path.$file); 
      } 
     } 
    } 
} 

3)使用捲曲,如果你沒有訪問啓用了allow_url_fopen。

4)如果您沒有安裝CURL並且無法安裝它,請使用外部程序,如wget。 5)最糟糕的情況:在遠程服務器上打開一個到80端口的套接字,然後發送一個HTTP請求給這個文件。

6)您的Web服務器可能能夠做某種代理重定向,這意味着您實際上不需要任何代碼來完成此操作,並且您可以免費獲得緩存和其他優化。例如,請參閱Apache的mod_proxy文檔:https://httpd.apache.org/docs/2.2/mod/mod_proxy.html

選項6是最好的,如果你可以。除此之外,前兩個是最有可能需要的,但我可以填寫一些示例代碼,如果你喜歡:)

+0

感謝您的答案!因爲我在WordPress插件中使用了這個功能,所以我不能依賴mod_proxy,但是我已經構建了可以使用的方法。所以它是2和3的混合 – Xaver