關于php:從URL下載文件到服務器
Download File to server from URL
嗯,這個看起來很簡單,確實如此。要將文件下載到服務器,只需執行以下操作:
file_put_contents("Tmpfile.zip", file_get_contents("http://someurl/file.zip"));
只有一個問題。如果你有一個大文件,比如100MB,怎么辦?然后,您將耗盡內存,無法下載該文件。
我想要的是一種在下載文件時將其寫入磁盤的方法。這樣,我可以下載更大的文件,而不會遇到內存問題。
- 這是在服務器配置中設置的,據我所知,PHP不能真正繞過它(除了直接的.in i編輯)
- 如果你看過這個問題,它沒有說任何關于改變記憶極限的事情。它說要在下載時將文件寫入磁盤。
- 沒有理由表現得粗魯無禮。
自從PHP 5.1.0,file_put_contents()以來,通過一條流過的手,如$data參數寫入零件:
file_put_contents("Tmpfile.zip", fopen("http://someurl/file.zip", 'r'));
From the Manual:
If data [that is the second argument] is a stream resource, the remaining buffer of that stream will be copied to the specified file. This is similar with using
stream_copy_to_stream().
謝謝你Hakre
- 那不是我的第一選擇。如果在php.ini中設置了allow_fopen_url Off(安全性的好主意),您的腳本將被破壞。
- @我認為,如果是這樣的話,file_get_contents()也不會起作用(見上圖)。
- @杰夫,我是具體的,我提到了你想要的功能。你可能想要的是有人為你寫代碼——但我相信你自己也學到了一些東西。此外,如果我們要對彼此的SO交互進行評論-請接受更多答案:)
- @亞歷克斯:請看編輯,請隨意合并。請告訴我何時可以刪除此評論。
- @謝謝,非常感謝。我會讓它更容易流動。:)
- 在大多數情況下,fopen也應使用"b"標志;防止對圖像和其他非純文本文件產生不利影響。
- 多虧這個保存了我的1GB移動數據,我計劃將文件從一個服務器傳輸到另一個服務器,我可以直接移動zip文件,而不是下載和上傳到新服務器。:)
private function downloadFile($url, $path) { $newfname = $path; $file = fopen ($url, 'rb'); if ($file) { $newf = fopen ($newfname, 'wb'); if ($newf) { while(!feof($file)) { fwrite($newf, fread($file, 1024 * 8), 1024 * 8); } } } if ($file) { fclose($file); } if ($newf) { fclose($newf); } }
- 謝謝,非常有用!
- 走這條路!
- 謝謝你的狙擊手,但你能解釋一下你的代碼@xaav嗎?我不太擅長PHP。1024*8是什么?再次感謝。
- @wminow行的長度。
- 具體來說,它意味著一次最多讀取8kb(1024字節/kb*8),因為參數以字節為單位。只要線路<=8kb,就可以一次讀取整條線路。
- 簡單而有效。很好;
- 為什么這不是最好的答案?
- 這應該是最好的答案。
- 這種方法如何處理錯誤?如果返回404或連接中斷或超時怎么辦?
- 這很有用,但是如果404通過,您將下載任何東西,并且您可以始終運行該文件的搜索檢查(某些邏輯),如果(!myfile)->中斷;
- 下載大型文件的最佳方法
- 非常快-你是真正的大師!
- 有時fopen failed to open stream: HTTP request failed! HTTP/1.1 403 Forbidden顯示這個錯誤是因為防止網絡爬行,如何解決呢?@阿馬爾·易卜拉欣
- nomanjaved您需要首先在登錄表單上執行auth請求,并為所有進一步的請求重用相同的curl客戶機(或者至少是頭和cookie)。
- 它如何無卷曲下載?
- 不使用HTTPS
- 下載0KB的空文件,盡管該文件超過17MB skype main.db文件。在php 5.4上,還必須從函數的開頭刪除"private"。
- 這個解決方案對我來說非常好,因為我必須下載一個巨大的XML文件,它超過了我的php內存限制(如果是1024m)。
我不確定,但我相信CURLOPT_FILE作為數據脈沖寫的,不是緩沖。
- 通常情況下,這是可以的,但我在一個Web應用程序中有這個代碼,所以我不能確定用戶是否安裝了curl。不過,我還是投了一票。
- @杰夫是分布式網絡應用嗎?因為如果您控制主機,那么它與您的用戶無關(curl是您服務器上的一個庫)。
- 不,我不控制主機。這是一個任何人都可以擁有的分布式Web應用程序。
- 卷發可能不見了。但幾乎所有共享主機公司都默認安裝了curl。我是說,我還沒見過一個沒有。
- 從我的測試來看,您不能直接將文件路徑分配給curlopt_文件。它必須是一個文件處理程序。首先用$fh = fopen('/path/to/download/the/file/to.zip', 'w');打開文件,在curl_close($ch);之后用fclose($fh);關閉。設置CURLOPT_FILE => $fh。
- 在目的地服務器中創建一個叫做"下載"的折頁
- 在目的地服務器中保存文件和運行
下載:
<html> <form method="post"> <input name="url" size="50" /> <input name="submit" type="submit" /> </form> <?php // maximum execution time in seconds set_time_limit (24 * 60 * 60); if (!isset($_POST['submit'])) die(); // folder to save downloaded files to. must end with slash $destination_folder = 'downloads/'; $url = $_POST['url']; $newfname = $destination_folder . basename($url); $file = fopen ($url,"rb"); if ($file) { $newf = fopen ($newfname,"wb"); if ($newf) while(!feof($file)) { fwrite($newf, fread($file, 1024 * 8 ), 1024 * 8 ); } } if ($file) { fclose($file); } if ($newf) { fclose($newf); } ?> </html>
- 這假設用戶需要一個獨立的腳本,而不是一個可以在現有的PHP應用程序中工作的解決方案,我相信后者正是OP和大多數其他應用程序所需要的。一個解釋也將有助于那些想了解這種方法的人。
- 每當我嘗試這個時,我傳輸的文件大小總是50816,但我的文件大小大于這個。120 MB。知道為什么嗎?
- set_time_limit (24 * 60 * 60);必須放在一個循環中。它在腳本開頭沒有效果。
Above there is examle(cited by prodigitalson)of code WCHIH not work(reason:missing fopen in curlopt ufile-http://www.webdeveloper.com/forum/showthread.php?(2.68299-resolved-php-script-for-a-cronjob-download-file-unpzck-run-another-php-script)。我無法添加如何使我的點數太低,以至于在下面我提供了一個例子(IT also work for"Local URL"):
function downloadUrlToFile($url, $outFileName) { if(is_file($url)) { copy($url, $outFileName); } else { $options = array( CURLOPT_FILE => fopen($outFileName, 'w'), CURLOPT_TIMEOUT => 28800, // set this to 8 hours so we dont timeout on big files CURLOPT_URL => $url ); $ch = curl_init(); curl_setopt_array($ch, $options); curl_exec($ch); curl_close($ch); } }
set_time_limit(0); $file = file_get_contents('path of your file'); file_put_contents('file.ext', $file);
- 你的回答很簡單,很好的工作,幫助我在curl找不到文件的地方,這個工作。謝謝)
- 你可能想解釋一下這到底是做什么的。
- 這并不能解決OP超過PHP內存限制的問題。
有三條路:
- 文件 U Get U Contents and File U Put U Contents
- 庫爾
- 福彭
你可以從這里找到例子。
使用簡單方法
copy($source_url, $local_path_with_file_name);
注釋:如果目的地文件已經存在,它將超過寫入。
復制函數
Special note:Don't forget to set permission 777 for the destination folder
我用這個下載文件
function cURLcheckBasicFunctions() { if( !function_exists("curl_init") && !function_exists("curl_setopt") && !function_exists("curl_exec") && !function_exists("curl_close") ) return false; else return true; } /* * Returns string status information. * Can be changed to int or bool return types. */ function cURLdownload($url, $file) { if( !cURLcheckBasicFunctions() ) return"UNAVAILABLE: cURL Basic Functions"; $ch = curl_init(); if($ch) { $fp = fopen($file,"w"); if($fp) { if( !curl_setopt($ch, CURLOPT_URL, $url) ) { fclose($fp); // to match fopen() curl_close($ch); // to match curl_init() return"FAIL: curl_setopt(CURLOPT_URL)"; } if ((!ini_get('open_basedir') && !ini_get('safe_mode')) || $redirects < 1) { curl_setopt($ch, CURLOPT_USERAGENT, '"Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1.11) Gecko/20071204 Ubuntu/7.10 (gutsy) Firefox/2.0.0.11'); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); //curl_setopt($ch, CURLOPT_REFERER, 'http://domain.com/'); if( !curl_setopt($ch, CURLOPT_HEADER, $curlopt_header)) return"FAIL: curl_setopt(CURLOPT_HEADER)"; if( !curl_setopt($ch, CURLOPT_FOLLOWLOCATION, $redirects > 0)) return"FAIL: curl_setopt(CURLOPT_FOLLOWLOCATION)"; if( !curl_setopt($ch, CURLOPT_FILE, $fp) ) return"FAIL: curl_setopt(CURLOPT_FILE)"; if( !curl_setopt($ch, CURLOPT_MAXREDIRS, $redirects) ) return"FAIL: curl_setopt(CURLOPT_MAXREDIRS)"; return curl_exec($ch); } else { curl_setopt($ch, CURLOPT_USERAGENT, '"Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1.11) Gecko/20071204 Ubuntu/7.10 (gutsy) Firefox/2.0.0.11'); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); //curl_setopt($ch, CURLOPT_REFERER, 'http://domain.com/'); if( !curl_setopt($ch, CURLOPT_FOLLOWLOCATION, false)) return"FAIL: curl_setopt(CURLOPT_FOLLOWLOCATION)"; if( !curl_setopt($ch, CURLOPT_FILE, $fp) ) return"FAIL: curl_setopt(CURLOPT_FILE)"; if( !curl_setopt($ch, CURLOPT_HEADER, true)) return"FAIL: curl_setopt(CURLOPT_HEADER)"; if( !curl_setopt($ch, CURLOPT_RETURNTRANSFER, true)) return"FAIL: curl_setopt(CURLOPT_RETURNTRANSFER)"; if( !curl_setopt($ch, CURLOPT_FORBID_REUSE, false)) return"FAIL: curl_setopt(CURLOPT_FORBID_REUSE)"; curl_setopt($ch, CURLOPT_USERAGENT, '"Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1.11) Gecko/20071204 Ubuntu/7.10 (gutsy) Firefox/2.0.0.11'); } // if( !curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true) ) return"FAIL: curl_setopt(CURLOPT_FOLLOWLOCATION)"; // if( !curl_setopt($ch, CURLOPT_FILE, $fp) ) return"FAIL: curl_setopt(CURLOPT_FILE)"; // if( !curl_setopt($ch, CURLOPT_HEADER, 0) ) return"FAIL: curl_setopt(CURLOPT_HEADER)"; if( !curl_exec($ch) ) return"FAIL: curl_exec()"; curl_close($ch); fclose($fp); return"SUCCESS: $file [$url]"; } else return"FAIL: fopen()"; } else return"FAIL: curl_init()"; }
a PHP 4&Amp 5 solution:
Readfile()will not present any memory issues,even when sending large files,on its own.一個URL可以用作此函數的文件名,如果FOPEN wrappers已經生成。
http://php.net/manual/en/function.readfile.php
- 這并不能回答問題,因為問題是寫在磁盤上,而不是寫到輸出緩沖區。

浙公網安備 33010602011771號