【问题标题】:php curl not saving file to locationphp curl没有将文件保存到位置
【发布时间】:2013-04-03 14:46:12
【问题描述】:

我整天都在寻找这个问题的答案,但没有运气!

我想将图像从网络下载/复制到我服务器上的某个位置,下面的代码不会引发任何错误,除了图像只是没有保存到所需的目录或任何目录。

如您所见,我正在使用 cURL 获取图像并且变量 $contents 返回 true (1),因此我假设脚本有效,但实际上我遗漏了一些东西。

非常感谢您的帮助。 :-)

    $dir = URL::base() . "/img/products/";

    $imgSrc = "an image on the web";

    $file = fopen($dir, "wb");

    $headers[] = 'Accept: image/gif, image/x-bitmap, image/jpeg, image/pjpeg';              
    $headers[] = 'Connection: Keep-Alive';         
    $headers[] = 'Content-type: application/x-www-form-urlencoded;charset=UTF-8';         
    $user_agent = 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)';  

    $ch = curl_init($imgSrc);
    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);         
    curl_setopt($ch, CURLOPT_HEADER, 0);         
    curl_setopt($ch, CURLOPT_USERAGENT, $user_agent); 
    curl_setopt($ch, CURLOPT_HEADER, 0);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_FILE, $file); // location to write to
    curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 60);
    $contents = curl_exec($ch);
    $curl_errno = curl_errno($ch);
    $curl_error = curl_error($ch);
    curl_close($ch);
    fclose($lfile);

    if ($curl_errno > 0) 
    {
        Log::write("CURL", "cURL Error (".$curl_errno."): ".$curl_error);
    } 
    else 
    {
        Log::write("CURL", "Data received: " . $contents);
    }

    return;

【问题讨论】:

  • 您没有指定正确的文件名... $dir 中仅存在目录路径。
  • 感谢您的回复我改成这个:$file = fopen($dir .basename($imgSrc), "wb");但我得到了相同的结果。
  • 改成绝对路径:$file = fopen("domain.co.uk/img/products/newfilename.jpg", "wb");仍然得到相同的结果。

标签: php curl laravel


【解决方案1】:

使用 curl 为文件提供对 PHP FILE 的写入权限以存储内容。这可以通过三种方式完成:

  • 如果您有终端访问权限,则使用 chmod 提供写入访问权限

  • 如果您有 CPanel 访问权限,则使用目录资源管理器,然后通过更改文件属性提供对文件的写入访问权限。

  • 您必须具有 FTP 访问权限并更改文件访问属性并提供写入访问权限。

【讨论】:

  • 我已经确保通过 cpanel 将目录权限设置为 777
【解决方案2】:

不要使用 curl。

如果您只需要下载图像,请改为使用“file_get_contents”。 很简单:

$fileContents = file_get_contents("https://www.google.com/images/srpr/logo4w.png");
File::put('where/to/store/the/image.jpg', $fileContents);

【讨论】:

  • 同意这要容易得多,但是 cURL 更可定制且更快。
  • 有趣,刚刚添加了您的代码,得到以下无法打开流:没有这样的文件或目录,在 laravel 中查看“堆栈跟踪”,它看起来像是试图将文件放在公共之外文件夹,但我看不到确切的位置?
  • 您可以通过将“where/to/store/the/image.jpg”更改为您喜欢的路径+文件名来指定应保存图像的位置。 Ben 是对的,如果速度很重要,你可能想搞乱 curl 的(可怕的 API)。
  • :-) 是的,这是漫长的一天!
【解决方案3】:
function saveImageToFile($image_url,$output_filename)
{
    $ch = curl_init ($url);
    curl_setopt($ch, CURLOPT_HEADER, 0);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_BINARYTRANSFER,1);
    $raw=curl_exec($ch);
    curl_close ($ch);
    if(file_exists($saveto))
    {
        unlink($saveto); //Saves over files
    }
    $fp = fopen($saveto,'x');
    fwrite($fp, $raw);
    fclose($fp);
}

【讨论】:

    【解决方案4】:

    您的问题很简单,我不知道其他人如何忽略它。它是 Laravel 特有的。您的 $dir 变量返回一个 HTTP 资源标识符。您需要的是一个文件系统标识符。

    对于 laravel,将你的 URL::to() 更改为 path("public") 以告诉 Laravel 停止使用 HTTP URI,而是使用公共文件夹的本地路径 (/your/laravel/setup/path/public /)。

    代码

    $dir = path("public") . "img/products/";
    
    $imgSrc = "an image on the web";
    
    $file = fopen($dir . substr($imgSrc,strrpos("/",$imgSrc)+1), "wb");
    
    $headers[] = 'Accept: image/gif, image/x-bitmap, image/jpeg, image/pjpeg';              
    $headers[] = 'Connection: Keep-Alive';         
    $headers[] = 'Content-type: application/x-www-form-urlencoded;charset=UTF-8';         
    $user_agent = 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)';  
    
    $ch = curl_init($imgSrc);
    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);         
    curl_setopt($ch, CURLOPT_HEADER, 0);         
    curl_setopt($ch, CURLOPT_USERAGENT, $user_agent); 
    curl_setopt($ch, CURLOPT_HEADER, 0);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_FILE, $file); // location to write to
    curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 60);
    $contents = curl_exec($ch);
    $curl_errno = curl_errno($ch);
    $curl_error = curl_error($ch);
    curl_close($ch);
    
    if ($curl_errno > 0) 
    {
        Log::write("CURL", "cURL Error (".$curl_errno."): ".$curl_error);
    } 
    else 
    {
        Log::write("CURL", "Data received: " . $contents);
        fwrite($file,$contents);
        fclose($file);
    
    }
    
    return;
    

    【讨论】:

    • 我有点明白,但显然不完全明白! :-) $dir = URL::to('public') 。 “/img/产品/”;或 $dir = URL::to('home/servername/public_html/img/products/');
    • 完全删除 url::to。稍后我将使用代码编辑我的答案。
    • 用一些代码编辑。我借此机会实际添加了一个fwrite 电话。我添加的substr 旨在从 URL 获取文件名。
    • 感谢这个 Sébastien,substr 对我不起作用,但 basename() 在我的情况下很好并且运行良好。我现在可以保存文件,但由于某种原因只能在我的开发机器上,当我在生产服务器上运行它时,我得到一个流错误:fopen(/img/products/php.gif):打开流失败:没有这样的文件或目录...我必须在生产站点上的 Laravel 中或它的上传方式有错误...我的核心 Laravel 路径常量设置为 '../apps/dhg/paths.php';所以它在 public_html 文件夹之外,并且公共目录的路径设置为 $paths['public'] = 'public';
    • 我把公共目录的路径改成了 $paths['public'] = 'public';但是文件没有保存,所以我将 $dir 更改为服务器上的绝对路径,现在一切正常!
    【解决方案5】:

    好的,终于搞定了,如果其他人尝试做同样的事情,这里是代码!

    我错过了这些部分:

        $dir = $_SERVER['DOCUMENT_ROOT'] . "/img/products/";
    

        fwrite($file,$contents);
    

    这是我的最终代码……感谢 Sébastien 为我指明了正确的方向。谢谢。

            if($method == 'save')
            {
                $productId = Input::get('pId');
                $removeProductImages = DB::table('product_ref_images')->where('product_id', '=', $productId)->delete();
    
                $imagesData = Input::get('imageRefs');
    
                $dir = $_SERVER['DOCUMENT_ROOT'] . "/img/products/";
    
                $sortOrder = 0;
    
                for ($i=0; $i < count($imagesData); $i++) {
    
                    $imgSrc = trim($imagesData[$i]['imgSrc']);
                    $imgId = trim($imagesData[$i]['imgId']);
    
                    $file = fopen($dir . basename($imgSrc), "wb");
    
                    $headers[] = 'Accept: image/gif, image/x-bitmap, image/jpeg, image/pjpeg';              
                    $headers[] = 'Connection: Keep-Alive';         
                    $headers[] = 'Content-type: application/x-www-form-urlencoded;charset=UTF-8';         
                    $user_agent = 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)';  
    
                    $ch = curl_init($imgSrc);
                    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);         
                    curl_setopt($ch, CURLOPT_HEADER, 0);         
                    curl_setopt($ch, CURLOPT_USERAGENT, $user_agent);
                    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
                    curl_setopt($ch, CURLOPT_FILE, $file);
                    curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 60);
                    $contents = curl_exec($ch);
                    $curl_errno = curl_errno($ch);
                    $curl_error = curl_error($ch);
                    curl_close($ch);
    
                    if ($curl_errno > 0) 
                    {
                        Log::write("CURL", "cURL Error (".$curl_errno."): ".$curl_error);
                        break;
                    } 
                    else 
                    {
                        fwrite($file,$contents);
                        fclose($file);
    
                        $imageIds = DB::table('product_ref_images')->order_by('image_id', 'desc')->first();
    
                        if($imageIds == null)
                        {
                            $imageIds = 0;
                        }
                        else
                        {
                            $imageIds = $imageIds->image_id;
                        }
    
                        $updateImages = DB::table('product_ref_images')
                            ->insert(array(
                                'image_id'          =>  $imageIds + 1,
                                'product_id'        =>  $productId,
                                'flickr_image_id'   =>  $imgId,
                                'sort_order'        =>  $sortOrder++,
                                'local_storage_url' =>  $dir . basename($imgSrc),
                                'created_at'        =>  date("Y-m-d H:i:s"),
                                'updated_at'        =>  date("Y-m-d H:i:s")
                        ));
                    }
                }
                return Response::json('Complete');
            }
    

    【讨论】:

    • 如果您删除了应用程序特定的部分,这将是一个更有帮助的答案,例如将图像插入数据库,答案包括解决问题的特定代码:)
    【解决方案6】:

    删除这一行:

     curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    

    您将响应存储到文件,而不是返回变量。否则,您必须自己保存它(就像您在其他解决方案中所做的那样)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-05-11
      • 2014-11-07
      • 2010-12-23
      • 2013-09-12
      相关资源
      最近更新 更多