Используя fopen, fwrite несколько раз в цикле foreach

Я хочу сохранить файлы с внешнего сервера в папку на моем сервере, используя fopen, fwrite.

Сначала загружается страница с внешнего сайта и сканируется на наличие ссылок на изображения. Затем этот список отправляется из функции fwrite. Файлы созданы, но они не являются действительными файлами jpg, при просмотре их в браузере кажется, что их путь на моем сервере записан в них.

Вот код:

//read the file
$data = file_get_contents("http://foo.html");

   //scan content for jpg links
preg_match_all('/src=("[^"]*.jpg)/i', $data, $result); 

//save img function
function save_image($inPath,$outPath)
{
    $in=    fopen($inPath, "rb");
    $out=   fopen($outPath, "wb");
    while ($chunk = fread($in,8192))
    {
        fwrite($out, $chunk, 8192);
    }
    fclose($in);
    fclose($out);
}

//output each img link from array
foreach ($result[1] as $imgurl) {
    echo "$imgurl<br />\n";
    $imgn = (basename ($imgurl));
    echo "$imgn<br />\n";
    save_image($imgurl, $imgn);
}

Функция save_image работает, если я выпишу список:

save_image('http://foo.html', foo1.jpg);
save_image('http://foo.html', foo1.jpg);

Я надеялся, что смогу просто зациклить список из совпадений в массиве.

Спасибо, что посмотрели.


person Nooga    schedule 06.03.2011    source источник


Ответы (4)


В вашем скрипте две проблемы. Во-первых, кавычка включается во внешний URL-адрес изображения. Чтобы исправить это, ваше регулярное выражение должно быть:

/src="([^"]*.jpg)/i

Во-вторых, URL-адреса изображений, вероятно, не являются абсолютными (не включайте http:// и путь к файлу). Поместите это в начало вашего foreach, чтобы исправить это:

$url = 'http://foo.html';
# If the image is absolute.
if(substr($imgurl, 0, 7) == 'http://' || substr($imgurl, 0, 8) == 'https://')
{
  $url = '';
}
# If the image URL starts with /, it goes from the website's root.
elseif(substr($imgurl, 0, 1) == '/')
{
  # Repeat until only http:// and the domain remain.
  while(substr_count($url, '/') != 2)
  {
    $url = dirname($url);
  }
}
# If only http:// and a domain without a trailing slash.
elseif(substr_count($imgurl, '/') == 2)
{
  $url .= '/';
}
# If the web page has an extension, find the directory name.
elseif(strrpos($url, '.') > strrpos($url, '/'))
{
  $url = dirname($url);
}
$imgurl = $url. $imgurl;
person Jumpey    schedule 06.03.2011

fopen не гарантирует работу. Вы должны проверять возвращаемые значения всего, что они могут вернуть при ошибке...

fopen() — возвращает ресурс указателя файла в случае успеха или FALSE в случае ошибки.

На самом деле все файловые функции возвращают false при ошибке.

Чтобы выяснить, где происходит сбой, я бы рекомендовал использовать отладчик или распечатать некоторую информацию в функции save_image. т. е. что такое $inPath и $outPath, чтобы вы могли проверить, что они передаются так, как вы ожидаете.

person Jacob    schedule 06.03.2011

Основная проблема, которую я вижу, заключается в том, что регулярное выражение может не захватить полный путь http://. Большинство сайтов отключают это и используют относительные пути. Вы должны закодировать чек для этого и добавить его, если этого нет.

person Jimithus    schedule 06.03.2011

Ваше совпадение включает бит src, поэтому попробуйте вместо этого:

preg_match_all('/(?<=src=")[^"]*.jpg/i', $data, $result); 

И тогда я думаю, что это должно работать:

unset($result[0]);
//output each img link from array
foreach ($result as $imgurl) {
    echo "$imgurl<br />\n";
    $imgn = (basename ($imgurl));
    echo "$imgn<br />\n";
    save_image($imgurl, $imgn);
}
person Highly Irregular    schedule 06.03.2011