Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/240.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用PHP fopen和/或cURL下载外部文件_Php_Curl_Http Headers_Download_Fopen - Fatal编程技术网

使用PHP fopen和/或cURL下载外部文件

使用PHP fopen和/或cURL下载外部文件,php,curl,http-headers,download,fopen,Php,Curl,Http Headers,Download,Fopen,我无法使我的下载脚本与外部文件一起工作,该文件将下载,但已损坏/无法工作。我想这是因为我无法使用filesize()函数获取外部文件的文件大小 这是我的剧本: function getMimeType($filename){ $ext = pathinfo($filename, PATHINFO_EXTENSION); $ext = strtolower($ext); $mime_types=array( "pdf" => "application

我无法使我的下载脚本与外部文件一起工作,该文件将下载,但已损坏/无法工作。我想这是因为我无法使用filesize()函数获取外部文件的文件大小

这是我的剧本:

function getMimeType($filename){
    $ext = pathinfo($filename, PATHINFO_EXTENSION);
    $ext = strtolower($ext);

    $mime_types=array(
        "pdf" => "application/pdf",
        "txt" => "text/plain",
        "html" => "text/html",
        "htm" => "text/html",
        "exe" => "application/octet-stream",
        "zip" => "application/zip",
        "doc" => "application/msword",
        "xls" => "application/vnd.ms-excel",
        "ppt" => "application/vnd.ms-powerpoint",
        "gif" => "image/gif",
        "png" => "image/png",
        "jpeg"=> "image/jpg",
        "jpg" =>  "image/jpg",
        "php" => "text/plain",
        "csv" => "text/csv",
        "xlsx" => "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
        "pptx" => "application/vnd.openxmlformats-officedocument.presentationml.presentation",
        "docx" => "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
    );

    if(isset($mime_types[$ext])){
        return $mime_types[$ext];
    } else {
        return 'application/octet-stream';
    }
}

$path = "http://www.example.com/file.zip";

/* Does not work on external files
// check file is readable or not exists
if (!is_readable($path))
    die('File is not readable or does not exists!');
*/

$file_headers = @get_headers($path);
if($file_headers[0] == 'HTTP/1.1 404 Not Found') {
    echo "Files does not exist.";
} else {

$filename = pathinfo($path, PATHINFO_BASENAME);

// get mime type of file by extension
$mime_type = getMimeType($filename);

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

// read file as chunk
if ( $fp = fopen($path, 'rb') ) {
    ob_end_clean();

    while( !feof($fp) and (connection_status()==0) ) {
        print(fread($fp, 8192));
        flush();
    }

    @fclose($fp);
    exit;
}

}
我相信卷发可以做到,但我的知识是缺乏的。 我想知道的是:

  • 如何检查文件是否存在,如何使用cURL获取文件大小

  • 使用cURL而忘记fopen会更好吗

  • 标题设置是否正确


任何建议都将不胜感激

问题来自设置为
0
的内容长度。 由于您已经从
get\u headers
调用中获得了内容长度,只需更改以下行:

header("Content-Length: " . filesize($path));
致:

请注意,
$file\u headers
的内容可能会有所不同(我用了8个),请查看详细信息,或执行
打印($file\u headers)
以查看其中的内容

如果您不关心内容长度标题,只需将其注释掉即可,大多数浏览器应该可以毫无问题地处理此问题。

功能:


尝试使用以下方法:

function get_data($url) 
{
    $ch = curl_init();
    $timeout = 5;
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
    $data = curl_exec($ch);
    curl_close($ch);

    return $data;
}
不幸的是,由于您缺乏关于特定查询或文件的详细信息,我无法提供更精确的代码来匹配您的情况。
上面(或下面)
curl\u get\u file\u size
将帮助您调整大小,以备您需要。

此代码可以从url下载:

set_time_limit(0);

//File to save the contents to
$fp = fopen ('r.jpg', 'w+');

$url = "http://cgr.ir/test.jpg";

//Here is the file we are downloading, replace spaces with %20
$ch = curl_init(str_replace(" ","%20",$url));

curl_setopt($ch, CURLOPT_TIMEOUT, 50);

//give curl the file pointer so that it can write to it
curl_setopt($ch, CURLOPT_FILE, $fp);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);

$data = curl_exec($ch);//get curl response

//done
curl_close($ch);
?>

您也可以尝试这个过程,我假设您的源url是
$sourceUrl
,保存文件的目标/路径是
$destinationPath

$destFilename = 'my_file_name.ext';
$destinationPath = 'your/destination/path/'.$destFilename;

if(ini_get('allow_url_fopen')) {                                
    if( ! @file_put_contents($destinationPath, file_get_contents($sourceUrl))){
        $http_status = $http_response_header[0];
        sprintf('%s encountered while attempting to download %s',$http_status, $sourceUrl );
        break;
    }
} elseif(function_exists('curl_init')) {
    $ch = curl_init($sourceUrl);
    $fp = fopen($destinationPath, "wb");

    $options = array(
        CURLOPT_FILE => $fp,
        CURLOPT_HEADER => 0,
        CURLOPT_FOLLOWLOCATION => 1,
        CURLOPT_TIMEOUT => 120); // in seconds

    curl_setopt_array($ch, $options);
    curl_exec($ch);
    $http_status = intval(curl_getinfo($ch, CURLINFO_HTTP_CODE));
    curl_close($ch);
    fclose($fp);

    //delete the file if the download was unsuccessful
    if($http_status != 200) {
        unlink($destinationPath);
        sprintf('HTTP status %s encountered while attempting to download %s', $http_status, $sourceUrl );

    }
} else {    
    sprintf('Looks like %s is off and %s is not enabled. No images were imported.', '<code>allow_url_fopen</code>', '<code>cURL</code>'  );
    break;
}

您可以使用
curl\u getinfo($ch,CURLINFO\u CONTENT\u TYPE)
如果是curl,请获取文件信息并根据您的要求使用。

我认为最好不要依赖php curl模块的可用性。您的代码片段只需稍加修改即可工作:

第一次改变

$file_headers = @get_headers($path);

获取命名数组键(请参见)

通过此修改,http状态代码仍然以$file_头[0]的形式出现,但您将获得更多有用的数据,这些数据可以通过(建议进行验证):内容长度,甚至内容类型(这允许您放弃对文件后缀进行mime类型检测的方法)

改变

header("Content-Length: " . filesize($path));


即使您的“路径”是一个受信任的源,您也可能需要添加一些验证,因为您不应该相信外部数据是您所期望的类型。

当您取消内容长度:标题时会发生什么。您能在输出之前下载整个文件吗?请提供调试问题时的一些输出。答案是肯定的,忘记
fopen
并使用
curl
。您应该意识到,设置正在执行的脚本标题对他试图通过fopen对外部url进行的查询没有太大影响。他的代码工作正常,使用fopen没有错,他唯一的问题是,他将0作为内容长度头传递。但我的问题是,为当前的
php脚本将返回的
设置的头(意思是使用
头()
),以及它对他在外部url上使用fopen进行的
查询的影响。我希望我能澄清一下。
$file_headers = @get_headers($path,1);
header("Content-Length: " . filesize($path));
header("Content-Length: " . $file_headers['Content-Length']);
header("Content-Type: $mime_type");
header("Content-Type: " . $file_headers['Content-Type']);