我正在尝试将远程文件(图像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会自动抛出异常。如何阻止此行为并自行检查状态,以便我可以自定义错误消息?
编辑:这是针对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时有更好/最合适的解决方案吗?
答案 0 :(得分:22)
您的代码可以简化很多。我下面的示例代码将直接将响应主体流式传输到文件系统。
<?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
文件系统mimetype?
当状态与200不同时,Guzzle会自动抛出异常。如何阻止此行为并自行检查状态,以便我可以自定义错误消息?
Guzzle将针对4xx和5xx等不良反应抛出异常。无需禁用此功能。只需捕获异常并处理错误。
答案 1 :(得分:10)
请看帖子:
public class Service {
@Autowired
private DAO dao;
public void method1() {
...
//System.out.println("DEBUG:" + dao.hashCode());
dao.XXX();
...
}
@Secured("...") // added second time (Case 2)
public void method2() {
...
dao.XXX();
...
}
}
public class ServiceTest {
@Mock
private DAO dao;
@InjectMocks
@Autowired
private Service service;
@Before
public void beforeTest() {
MockitoAnnotations.initMocks(this);
}
public void testMethod1() {
Mockito.when(dao.XXX()).thenReturn(...);
//System.out.println("DEBUG:" + dao.hashCode());
...
}
public void testMethod2() {
Mockito.when(dao.XXX()).thenReturn(...);
...
}
}
在这里你必须发送你的“帖子”的请求
并使用get
$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);
在这里你不需要发送请求, 和here你会找到很多文档,你必须有6个这样做,如果你同时使用GOUTTE你需要goutte 3.1,在你的composer.json中更新你的需求< / p>
答案 2 :(得分:2)
使用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"
);
}