Скопируйте удаленный файл с помощью Guzzle - программирование
Подтвердить что ты не робот

Скопируйте удаленный файл с помощью Guzzle

Я пытаюсь скопировать удаленный файл (изображение PNG, GIF, JPG...) на мой сервер. Я использую Guzzle, так как иногда получаю 404 с copy(), даже если файл существует, и мне также нужно сделать базовый auth. Этот script находится в длинном script запущенном в команде, вызванном заданием cron. Я новичок в Guzzle, и я успешно копирую изображение, но у моих файлов неправильный тип mime. Я должен делать что-то не так. Пожалуйста, предложите мне хороший способ сделать это (в том числе проверить успех/неудачу копирования и проверки типа mime). Если файл не имеет типа mime, я бы вынул ошибку с информацией о деталях.

Вот код:

$remoteFilePath = 'http://example.com/path/to/file.jpg';
$localFilePath = '/home/www/path/to/file.jpg';
try {
    $client = new Guzzle\Http\Client();
    $response = $client->send($client->get($remoteFilePath)->setAuth('login', 'password'));
    if ($response->getBody()->isReadable()) {
        if ($response->getStatusCode()==200) {
            // is this the proper way to retrieve mime type?
            //$mime = array_shift(array_values($response->getHeaders()->get('Content-Type')));
            file_put_contents ($localFilePath , $response->getBody()->getStream());
            return true;
        }
    }
} catch (Exception $e) {
    return $e->getMessage();
}

Когда я делаю это, мой тип mime устанавливается в application/x-empty

Также похоже, что когда статус отличается от 200, Guzzle автоматически генерирует исключение. Как я могу остановить это поведение и проверить статус самостоятельно, чтобы я мог настраивать сообщение об ошибке?

EDIT: Это было для Guzzle 3.X Теперь вы можете сделать это, используя Guzzle v 4.X(работает также с Guzzle 6)

$client = new \GuzzleHttp\Client();
$client->get(
    'http://path.to/remote.file',
    [
        'headers' => ['key'=>'value'],
        'query'   => ['param'=>'value'],
        'auth'    => ['username', 'password'],
        'save_to' => '/path/to/local.file',
    ]);

Или используя поток Gzzle:

use GuzzleHttp\Stream;

$original = Stream\create(fopen('https://path.to/remote.file', 'r')); 
$local = Stream\create(fopen('/path/to/local.file', 'w')); 
$local->write($original->getContents());

Это выглядит великолепно. Есть ли лучшее/правильное решение при использовании Guzzle 4?

4b9b3361

Ответ 1

Ваш код можно упростить. Мой примерный код ниже будет передавать тело ответа непосредственно в файловую систему.

<?php

function copyRemote($fromUrl, $toFile) {
    try {
        $client = new Guzzle\Http\Client();
        $response = $client->get($fromUrl)
            ->setAuth('login', 'password') // in case your resource is under protection
            ->setResponseBody($toFile)
            ->send();
        return true;
    } catch (Exception $e) {
        // Log the error or something
        return false;
    }
}

Когда я делаю это, мой тип mime устанавливается в application/x-empty

Миграция файловой системы?

Также похоже, что когда статус отличается от 200, Guzzle автоматически генерирует исключение. Как я могу остановить это поведение и проверить статус самостоятельно, чтобы я мог настраивать сообщение об ошибке?

Guzzle выдаст исключение для плохих ответов, таких как 4xx и 5xx. Не нужно отключать это. Просто поймайте исключение и обработайте ошибку там.

Ответ 2

Посмотрите на это с сообщением:

$myFile = fopen('path/to/file', 'w') or die('Problems');
$client = new \Guzzle\Service\Client();
$request = $client->post('https://www.yourdocumentpage.com', array(), ['pagePostField' => 'data'], ['save_to' => $myFile]);
$client->send($request);
fclose($myFile);

здесь вы должны отправить запрос своего "сообщения"

и с get

$myFile = fopen('path/to/file', 'w') or die('Problems');
$client = new \GuzzleHttp\Client();
$request = $client->get('https://www.yourdocumentpage.com', ['save_to' => $myFile]);

и здесь вам не нужно отправлять запрос, и здесь вы найдете много документации, для этого вам понадобится gzzle 6, и если вы используете GOUTTE одновременно вам понадобится goutte 3.1, обновите свой запрос в своем composer.json