laravel — проверяет, может ли PHP `copy` загружать файл из интернета

Я написал функцию с модульным тестом для загрузки изображения с использованием PHP

// ...
if (!copy($url, $imagePath)) {
return null;
}
// ...

Это работает локально, но в Bitbucket Pipelines модульный тест не пройден. Файл не может быть загружен (файл не найден в хранилище).

Возможно, он был отключен специально. Поэтому я хотел бы запустить этот тестовый модуль, только если copy() Можно загружать внешние файлы.

Я попробовал это, но не сработало:

public function test_downloadImage()
{
if (!ini_get('allow_url_fopen') || in_array('copy', explode(',', ini_get('disable_functions')))) {
return;
}
// download the image...
// assert file exists...
}

Как я могу проверить, если copy() можно скачать внешние файлы?

Спасибо.

Извините за это, но проблема не пришла из PHP copy(),

Он пытался загрузить изображение в несуществующий каталог. На самом деле, я забыл настроить Laravel Public directory символическая ссылка. Это было уже настроено на моем компьютере.

1

Решение

использование curl чтобы инициировать запрос HEAD:

function url_is_readable($url) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'HEAD');
curl_setopt($ch, CURLOPT_HEADER, 1);
curl_setopt($ch, CURLOPT_NOBODY, true);
curl_setopt($ch, CURLOPT_URL, $url);
$res = curl_exec($ch);
return false !== $res;
}

Тогда проверь:

var_dump(url_is_readable('https://imgs.xkcd.com/comics/im_so_random.png'));
var_dump(url_is_readable('http://whyohwhy.example.co/monkey.png'));

Вы можете использовать curl выполнить копию. Это имеет несколько преимуществ. Во-первых, он работает независимо от того, allow_url_fopen был выключен Во-вторых, curl дает вам гораздо больше контроля, диагностики и информации об ошибках. В-третьих, это круче. 🙂

1

Другие решения

Рассмотрите возможность переключения на curl как allow_url_fopen часто отключается по соображениям безопасности.


Однако, чтобы ответить на ваш вопрос, вы можете использовать метод, описанный Вот для file_get_contents (), чтобы проверить, можете ли вы получить контент из Интернета.

  1. Подавить предупреждение с @ перед file_get_contents (как предложено Руководство по PHP, но НЕ используйте это, если вы можете избежать этого)
  2. Проверьте возвращаемое значение для null
  3. Бросить исключение

Пример:

public function test_downloadImage($path)
{
$contents = @file_get_contents($path);
if($contents === null) {
$error = error_get_last();
throw new Exception($error['message']);
}
return $contents;
}

Вызовите эту функцию с помощью try / catch:

try {
$fileContent = test_downloadImage('http://stackoverflow.com')
// Success, do something with your file
} catch (Exception $e) {
// Download failed, log error from $e->getMessage(), show message to user
}
0