web-dev-qa-db-fra.com

Copier un fichier distant en utilisant Guzzle

J'essaie de copier un fichier distant (image au format PNG, GIF, JPG ...) sur mon serveur. J'utilise Guzzle puisque je reçois parfois 404 avec copy () même si le fichier existe et que je dois également effectuer une authentification de base. Ce script fait partie d’un long script lancé dans une commande déclenchée par un travail cron. Je suis assez nouveau dans Guzzle et je copie correctement l’image, mais mes fichiers ont un type mime incorrect. Je dois faire quelque chose de mal ici. S'il vous plaît, suggérez-moi un bon moyen de le faire (notamment en vérifiant le succès/l'échec de la vérification de type copie et mime). Si le fichier n'a pas de type mime, une erreur avec des informations détaillées apparaît.

Voici le code:

$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();
}

Quand je fais cela, mon type mime est défini sur application/x-empty 

En outre, il semble que lorsque le statut est différent de 200, Guzzle lève automatiquement une exception. Comment puis-je arrêter ce comportement et vérifier moi-même l'état pour pouvoir personnaliser le message d'erreur?

EDIT: C'était pour Guzzle 3.X Voici comment procéder avec Guzzle v 4.X (fonctionne aussi avec 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',
    ]);

Ou en utilisant le flux Guzzle:

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());

Cela a l'air bien. Existe-t-il une solution meilleure/appropriée lors de l’utilisation de Guzzle 4?

17
Spir

Votre code peut être grandement simplifié. Mon exemple de code ci-dessous transmettra le corps de la réponse directement au système de fichiers.

<?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;
    }
}

Quand je fais cela, mon type mime est défini sur application/x-empty

Un type de fichier MIME?

En outre, il semble que lorsque le statut est différent de 200, Guzzle lève automatiquement une exception. Comment puis-je arrêter ce comportement et vérifier moi-même l'état pour pouvoir personnaliser le message d'erreur?

Guzzle lève une exception pour les mauvaises réponses comme 4xx et 5xx. Pas besoin de désactiver ceci. Attrapez juste une exception et traitez l'erreur ici.

21
Michael Dowling

Regardez ceci avec post:

$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);

ici vous devez envoyer la demande de votre "post"

et avec get

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

et ici vous n’avez pas besoin d’envoyer la demande, et ici vous trouverez beaucoup de documentation, vous devez en avoir 6 pour le faire, et si vous utilisez GOUTTE en même temps temps vous aurez besoin de goutte 3.1, mettez à jour votre besoin dans votre composer.json

10
Jorgeeadan

en utilisant Guzzle 6, utilisez simplement l'option SINK. voir ci-dessous la fonction détaillée 

Supplémentaire:

utilisez GuzzleHttp\Client; Espace de nommage inclus

$ access_token = si vous avez besoin d'authentification, supprimez simplement cette option

ReportFileDownloadException = exception personnalisée

/**
 * download report file and read data to database
 * @param remote url
 * @return N/A
 * @throws ReportFileDownloadException
 */
protected function getReportFile($report_file_url)
{
    $file = $this->tempDirectory . "/" . basename($report_file_url);
    $fileHandle = fopen($file, "w+");

    try {
        $client = new Client();
        $response = $client->get($report_file_url, [
            RequestOptions::SINK => $fileHandle,
            RequestOptions::HEADERS => [
                "Authorization" => "Bearer $access_token"
            ]
        ]);
    } catch (RequestException $e) {
        throw new ReportFileDownloadException(
            "Can't download report file $report_file_url"
        );
    } finally {
        @fclose($fileHandle);
    }

    throw new ReportFileDownloadException(
        "Can't download report file $report_file_url"
    );
}
2
Furqan Freed