web-dev-qa-db-ja.com

Guzzleを使用してリモートファイルをコピーする

リモートファイル(画像PNG、GIF、JPGなど)をサーバーにコピーしようとしています。私は Guzzle を使用します。ファイルが存在し、基本的な認証を行う必要がある場合でも、 copy() で404が発生することがあります。このスクリプトは、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',
    ]);

または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());

これは素晴らしいですね。 Guzzle 4を使用する場合、より良い/適切なソリューションはありますか?

18
Spir

コードは大幅に簡略化できます。以下のサンプルコードは、応答の本文を直接ファイルシステムにストリーミングします。

<?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に設定されます

ファイルシステムのMIMEタイプ?

また、ステータスが200と異なる場合、Guzzleは自動的に例外をスローします。この動作を停止してステータスを自分で確認して、カスタムエラーメッセージを表示するにはどうすればよいですか?

Guzzleは、4xxや5xxなどの悪い応答に対して例外をスローします。これを無効にする必要はありません。例外をキャッチして、そこでエラーに対処するだけです。

22
Michael Dowling

投稿でこれを見てください:

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

そしてここではリクエストを送信する必要はありません、そして here たくさんのドキュメントを見つけるでしょう、それを行うにはguzzle 6が必要です、そして同時にGOUTTEを使用しているなら'goutte 3.1が必要です。composer.jsonでrequireを更新してください

10
Jorgeeadan

guzzle 6を使用する場合は、SINKオプションを使用するだけです。以下の詳細な機能を参照してください

追加:

guzzleHttp\Clientを使用します。含まれるGuzzle名前空間

$ access_token =認証が必要な場合は、このオプションを削除してください

ReportFileDownloadException =カスタム例外

/**
 * 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