Может войдёшь?
Черновики Написать статью Профиль

Download url with self-signed HTTPS

В документации по Laravel тут и его английском варианте весьма неявно указано, как производить загрузку внешних файлов.

Цитирую оригинал

The put method may be used to store raw file contents on a disk. You may also pass a PHP resource to the PHPput method, which will use Flysystem's underlying stream support. Using streams is greatly recommended when dealing with large files:

PHP
use Illuminate\Support\Facades\Storage;

Storage::put('file.jpg'$contents);
Storage::put('file.jpg'$resource);

Или в нашем переводе

Для записи файла на диск служит метод PHPput(). Также вы можете передать в метод PHPput() PHP-resource, чтобы использовать низкоуровневую поддержку потоков Flysystem. Очень рекомендуем использовать потоки при работе с большими файлами:

Однако примеров такого использования не приведено ни в оригинале, ни в переводе статьи.

Между тем такая загрузка весьма проста в использовании:

PHP
          $resource = \fopen($url'r');
          
$disk Storage::disk('public');
          
$disk->put($path$resource);
          \
fclose($resource);

Всё было бы просто, но есть подводные камни. Как оказалось, для загрузки самоподписаных сертификатов нужны некоторые танцы с бубном, без которых система будет выдавать нечто вроде

fopen(): SSL operation failed with code 1. OpenSSL Error messages:
error:1416F086:SSL routines:tls_process_server_certificate:certificate verify failed

Обратившись к документации по fopen можно найти, что ему необходимо передать контекст

PHP
          $context stream_context_create([
              
'ssl' => [
                  
'verify_peer'      => false,
                  
'verify_peer_name' => false,
              ]
          ]);
          
$resource = \fopen($url'r'false$context);
          
$disk Storage::disk('public');
          
$disk->put($path$resource);
          \
fclose($resource);

Однако при таком запросе можно получить что то типа

failed to open stream: HTTP request failed! HTTP/1.0 400 Bad Request

Причина такого поведения кроется в самом ответе от сервера: HTTP 1.1 required

PHP
          $context stream_context_create([
              
'http' => [
                  
'protocol_version' => '1.1',
              ],
              
'ssl' => [
                  
'verify_peer'      => false,
                  
'verify_peer_name' => false,
              ]
          ]);
          
$resource = \fopen($url'r'false$context);
          
$disk Storage::disk('public');
          
$disk->put($path$resource);
          \
fclose($resource);

Получилось несколько громоздко, однако плюсом такого решения будет автоматическое создание путей $path

Альтернативным решением будет использовать GuzzleHttp

PHP
      $client = new Client(['verify' => false]);
      
$client->request('GET'$url, [
        
'sink' => $path,
      ]);

Но тогда придется позаботится о создании директорий.

В обоих случаях файл может быть любых размеров, память на него не расходуется.

P.S. Индусам, поставившим self-signed на VSOM в локальной сети уготовлено отдельное место в аду.

Как вы считаете, полезен ли этот материал? Да Нет

Написать комментарий

Разметка: ? ?

Авторизуйся, чтобы прокомментировать.