关于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

  • 这并不能回答问题,因为问题是写在磁盘上,而不是写到输出缓冲区。

 

 
 
posted @ 2024-08-01 16:14  mingruqi  阅读(46)  评论(0编辑  收藏  举报