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
- 这并不能回答问题,因为问题是写在磁盘上,而不是写到输出缓冲区。