提问者:小点点

在Foreach循环中使用file_put_contents只下载最后一项


我试图通过循环下载mp4文件的大列表,并使用file_put_contents()将其保存到目录中。问题是只有视频列表中的最后一项被下载。

这是我的密码:

<?php
$i = 0;
foreach ($response['videos'] as $row){
    $i++;
    if($row['status'] != 'failed') {
        $videoId= '';
        $videoName = '';
        $videoId = $row['key'];
        $videoName = $row['title'];
        $filename = '';
        $filename = str_replace(' ','-',$videoName); // remove spaces from filename created by name
        

        // Initialize a file URL to the variable
        $url = "";
        $url = "http://content.jwplatform.com/videos/{$videoId}.mp4";
          
        // Use file_get_contents() function to get the file
        // from url and use file_put_contents() function to
        // save the file
        if (file_put_contents("Videos/".$filename.$i.".mp4", file_get_contents($url)))
        {
            echo "File downloaded successfully.";
            //sleep(5);
        }
        else
        {
            echo "File downloading failed.";
        }
        
    }
}
?>

我试着用一个CURL函数来代替file_put_contents(),它成功地将所有文件放到了我的视频目录中,但它们都是空文件。我相信它们是空的,因为这些mp4 URL是安全视频,所以当你在浏览器中打开它们时,它们实际上会将你带到另一个安全URL以查看和下载视频。CURL函数无法成功地获取文件数据,但似乎file_get_contents()确实成功地获取了文件数据(尽管只有最后一项)。

在我上面的代码中,我相信发生的是循环中的变量被一次又一次地重写,直到它到达最后一项,然后执行file_put_contents()函数。如果是这种情况,我如何确保它在每个循环上执行函数,以便下载所有文件?

编辑:以下是var_导出的一些输出($response['videos'))

array ( 0 => array ( 'key' => 'eewww123', 'title' => 'Video Name Example 1', 'description' => NULL, 'date' => 1604004019, 'updated' => 1640011490, 'expires_date' => NULL, 'tags' => NULL, 'link' => NULL, 'author' => NULL, 'size' => '240721720', 'duration' => '229.79', 'md5' => 'f0023423423423423423', 'views' => 0, 'status' => 'ready', 'error' => NULL, 'mediatype' => 'video', 'sourcetype' => 'file', 'sourceurl' => NULL, 'sourceformat' => NULL, 'upload_session_id' => NULL, 'custom' => array ( ), ), 1 => array ( 'key' => 'rr33445', 'title' => 'Another Video Name Example 1', 'description' => '', 'date' => 1594316349, 'updated' => 1640011493, 'expires_date' => NULL, 'tags' => NULL, 'link' => '', 'author' => NULL, 'size' => '525702235', 'duration' => '840.90', 'md5' => '0044455sfsdgsdfs3245', 'views' => 0, 'status' => 'ready', 'error' => NULL, 'mediatype' => 'video', 'sourcetype' => 'file', 'sourceurl' => NULL, 'sourceformat' => NULL, 'upload_session_id' => NULL, 'custom' => array ( ), ), )

没有一行有失败的状态,总共大约有30行,但我还有一些其他的视频列表下载900行。

下面是我使用的CURL函数,它成功下载了所有文件名,但所有文件都是空的:

    function multiple_download(array $urls, $save_path = 'Videos') {
    $multi_handle = curl_multi_init();
    $file_pointers = [];
    $curl_handles = [];

    // Add curl multi handles, one per file we don't already have
    foreach ($urls as $key => $url) {
        $file = $save_path . '/' . basename($url);
        if(!is_file($file)) {
            $curl_handles[$key] = curl_init($url);
            $file_pointers[$key] = fopen($file, "w");
            curl_setopt($curl_handles[$key], CURLOPT_FILE, $file_pointers[$key]);
            curl_setopt($curl_handles[$key], CURLOPT_HEADER, 0);
            curl_setopt($curl_handles[$key], CURLOPT_CONNECTTIMEOUT, 60);
            curl_multi_add_handle($multi_handle,$curl_handles[$key]);
        }
    }

    // Download the files
    do {
        curl_multi_exec($multi_handle,$running);
    } while ($running > 0);

    // Free up objects
    foreach ($urls as $key => $url) {
        curl_multi_remove_handle($multi_handle, $curl_handles[$key]);
        curl_close($curl_handles[$key]);
        fclose ($file_pointers[$key]);
    }
    curl_multi_close($multi_handle);
}



multiple_download($videoURLS);

$video oURLs是我使用上面的第一个PHP函数构建的一个数组,其中包含所有唯一的URL(其他部分注释掉了)。


共1个答案

匿名用户

您必须使用标志附加到文件,而不是覆盖。

见文件https://www.php.net/manual/fr/function.file-put-contents.php标志文件

编辑:如果所有文件都具有相同的名称,则可能会覆盖它们。必须在循环中提供不同的名称。

foreach ($response['videos'] as $key => $row) {
    ...
    if (file_put_contents("Videos/" . $filename .$key ".mp4", file_get_contents($url))) {
   ...

在文件名中使用循环的$key使其uniq并且不会被覆盖