如何使用 symfony 4 从 csv 提要 URL 下载数据?
How to download data from a csv feed URL with symfony 4?
使用 Symfony 4,我需要从远程下载数据 URL。我可以使用 Symfony 4 还是需要使用 JQuery 或 Python 或...?我是解析 URL 的内容还是可以从 URL 下载 csv 文件?
我是新手,请把我当傻瓜一样交流。
我正在 Symfony 4 中开发一个 Web 应用程序,它应该从合作商店下载数据(通过 symfony 命令和 CRON 任务),这要归功于他们在自己的 Web 应用程序上提供的 URL,例如这个:
Wine Title Vintage Country Region Sub region Appellation Color Bottle Size Price URL FORMAT
The Last Drop 1971 Scotch Scotland 750ML 3999.99 HTTP://buckhead.towerwinespirits.com/sku63174.html 1x750ML
Petrus Pomerol 2015 France Bordeaux 750ML 3799.99 HTTP://buckhead.towerwinespirits.com/sku40582.html 1x750ML
Remy Martin Louis XIII Cognac France Cognac 750ML 3499.99 HTTP://buckhead.towerwinespirits.com/sku15758.html 1x750ML
Hennessy Paradis Imperial Cognac France Cognac 750ML 3299.99 HTTP://buckhead.towerwinespirits.com/sku51487.html 1x750ML
我看过这个帖子:
how to download a file from a url with javascript?
第一个答案看起来很有趣,但正如我所说,我是新手,我不知道如何在我的命令中实现脚本。
我还看到了 Ruby 或 Angular 的其他讨论帖:
How to display and import data from a feed url?
但对我帮助不大...
编辑:我试图将 url 传递给 fopen 但它 returns HTTP/1.1 403 禁止:访问被拒绝。
更新:这是我到目前为止的代码(我承认不多),包含我尝试过的所有内容和结果:
class UpdateArticlesCommand extends Command
{
protected static $defaultName = 'app:update-articles';
protected $em = null;
protected function configure()
{
$this
->setDescription('Updates the articles of the stores having set a feed URL')
->setHelp('This command allows you to update the articles of the stores which have submitted a feed URL');
}
/**
* UpdateArticlesCommand constructor.
* @param EntityManagerInterface $em
* @param string|null $name
*/
public function __construct(EntityManagerInterface $em, ?string $name = null)
{
$this->em = $em;
parent::__construct($name);
}
protected function execute(InputInterface $input, OutputInterface $output)
{
$io = new SymfonyStyle($input, $output);
$io->title('Attempting to import the feeds...');
$converter = new ConverterToArray();
$io->writeln([$store->getFeedUrl()]);
$url = $store->getFeedUrl();
// dd($url); //OK
$feedColumnsMatch = $store->getFeedColumnsMatch();
// dd($feedColumnsMatch); //OK
$fileName = $store->getName().'Feed.txt';
$filePath = $fileUploader->getTargetDirectory() . "/" . $fileName;
/* //sends a http request and save the given file
set_time_limit(0);
$fp = fopen($filePath, 'x+');
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_TIMEOUT, 50);
// give curl the file pointer so that it can write to it
curl_setopt($ch, CURLOPT_FILE, $fp);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
$data = curl_exec($ch);//get curl response
curl_close($ch);
dd($data); //return false*/
/*dd($this->curl_get_file_contents($url)); //returns false*/
$client = new Client();
$response = $client->request('GET', $url);
echo $response->getStatusCode(); # 200
echo $response->getHeaderLine('content-type'); // 'application/json; charset=utf8'
echo $response->getBody(); // '{"id": 1420053, "name": "guzzle", ...}'
$articlesArray = $converter->convert("https://myURL.com", $feedColumnsMatch);
}
$io->success('Successful upload');
}
这是我的转换器的代码:
/**
* is used to convert a csv file into an array of data
* @param $filePath
* @param FeedColumnsMatch $feedColumnsMatch
* @return array|string
*/
public function convert($filePath, $feedColumnsMatch)
{
// if(!file_exists($filePath) ) {
// return "existe pas";
// }
// if(!is_readable($filePath)) {
// return "pas lisible";
// }
//this array will contain the elements from the file
$articles = [];
$headerRecord = [];
if($feedColumnsMatch->getFeedFormat()==="tsv" | $feedColumnsMatch->getFeedFormat()==="csv"){
if($feedColumnsMatch->getFeedFormat()==="csv"){
$delimiter = $feedColumnsMatch->getDelimiter();
}else{
$delimiter = "\t";
}
//if we can open the file on mode "read"
if (($handle = fopen($filePath, 'r')) !== FALSE) {
//represents the line we are reading
$rowCounter = 0;
//as long as there are lines
while (($rowData = fgetcsv($handle, 1000, $delimiter)) !== FALSE) {
//At first line are written the keys so we record them in $headerRecord
if(0 === $rowCounter){
$headerRecord = $rowData;
}else{ //for every other lines...
foreach ($rowData as $key => $value){ //in each line, for each value
// we set $value to the cell ($key) having the same horizontal position than $value
// but where vertical position = 0 (headerRecord[]
$articles[$rowCounter][$headerRecord[$key]]= $value;
}
}
$rowCounter++;
}
fclose($handle);
}
}
return $articles;
}
我想我错过了一步。我无法直接从 URL 读取文件,因此我必须在尝试读取文件之前先检索该文件。我该怎么做?
要从供稿 URL 下载数据,在我的例子中是一个 csv 文件,
您必须向 URL 发送请求。 Symfony 的设计目的不是向外部 URL 发送请求,因此您必须使用 cURL 或 Goutte or Guzzle。
我选择了古泽尔。以下是我的使用方法:
$client = new Client();
$response = $client->request('GET', $url);
echo "Status Code = ".$response->getStatusCode()."\n"; # 200
echo 'Content Type = '.$response->getHeaderLine('content-type')."\n";
$body = $response->getBody();
$url 是 url 我必须将请求发送到。
不要忘记在命名空间和 class 之间导入 Guzzle:
使用 GuzzleHttp\Client; .
使用此代码,您可以获得整个页面主体,即您获得的内容包含 html 标签,例如:
<!DOCTYPE html>
<html lang="en">
<body>
<pre>
Wine Directory List
<BR>
//here is the content of the csv file
</pre>
</body>
</html>
获得数据后,必须将其写入文件,以便创建
$filePath = 'public/my_data/myFile';
你 create/open 文件:
$fp = fopen($filePath, 'x');
然后你在文件中写入:
fwrite($fp, $body);
并且不要忘记关闭文件以避免内存泄漏:
fclose($fp);
最后,您只需在方便时转换文件即可。请记住,fopen() 中的模式 'x' 会创建一个文件,如果同名文件已存在,则会 returns 出错。
使用 Symfony 4,我需要从远程下载数据 URL。我可以使用 Symfony 4 还是需要使用 JQuery 或 Python 或...?我是解析 URL 的内容还是可以从 URL 下载 csv 文件?
我是新手,请把我当傻瓜一样交流。
我正在 Symfony 4 中开发一个 Web 应用程序,它应该从合作商店下载数据(通过 symfony 命令和 CRON 任务),这要归功于他们在自己的 Web 应用程序上提供的 URL,例如这个:
Wine Title Vintage Country Region Sub region Appellation Color Bottle Size Price URL FORMAT
The Last Drop 1971 Scotch Scotland 750ML 3999.99 HTTP://buckhead.towerwinespirits.com/sku63174.html 1x750ML
Petrus Pomerol 2015 France Bordeaux 750ML 3799.99 HTTP://buckhead.towerwinespirits.com/sku40582.html 1x750ML
Remy Martin Louis XIII Cognac France Cognac 750ML 3499.99 HTTP://buckhead.towerwinespirits.com/sku15758.html 1x750ML
Hennessy Paradis Imperial Cognac France Cognac 750ML 3299.99 HTTP://buckhead.towerwinespirits.com/sku51487.html 1x750ML
我看过这个帖子:
how to download a file from a url with javascript?
第一个答案看起来很有趣,但正如我所说,我是新手,我不知道如何在我的命令中实现脚本。
我还看到了 Ruby 或 Angular 的其他讨论帖:
编辑:我试图将 url 传递给 fopen 但它 returns HTTP/1.1 403 禁止:访问被拒绝。
更新:这是我到目前为止的代码(我承认不多),包含我尝试过的所有内容和结果:
class UpdateArticlesCommand extends Command
{
protected static $defaultName = 'app:update-articles';
protected $em = null;
protected function configure()
{
$this
->setDescription('Updates the articles of the stores having set a feed URL')
->setHelp('This command allows you to update the articles of the stores which have submitted a feed URL');
}
/**
* UpdateArticlesCommand constructor.
* @param EntityManagerInterface $em
* @param string|null $name
*/
public function __construct(EntityManagerInterface $em, ?string $name = null)
{
$this->em = $em;
parent::__construct($name);
}
protected function execute(InputInterface $input, OutputInterface $output)
{
$io = new SymfonyStyle($input, $output);
$io->title('Attempting to import the feeds...');
$converter = new ConverterToArray();
$io->writeln([$store->getFeedUrl()]);
$url = $store->getFeedUrl();
// dd($url); //OK
$feedColumnsMatch = $store->getFeedColumnsMatch();
// dd($feedColumnsMatch); //OK
$fileName = $store->getName().'Feed.txt';
$filePath = $fileUploader->getTargetDirectory() . "/" . $fileName;
/* //sends a http request and save the given file
set_time_limit(0);
$fp = fopen($filePath, 'x+');
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_TIMEOUT, 50);
// give curl the file pointer so that it can write to it
curl_setopt($ch, CURLOPT_FILE, $fp);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
$data = curl_exec($ch);//get curl response
curl_close($ch);
dd($data); //return false*/
/*dd($this->curl_get_file_contents($url)); //returns false*/
$client = new Client();
$response = $client->request('GET', $url);
echo $response->getStatusCode(); # 200
echo $response->getHeaderLine('content-type'); // 'application/json; charset=utf8'
echo $response->getBody(); // '{"id": 1420053, "name": "guzzle", ...}'
$articlesArray = $converter->convert("https://myURL.com", $feedColumnsMatch);
}
$io->success('Successful upload');
}
这是我的转换器的代码:
/**
* is used to convert a csv file into an array of data
* @param $filePath
* @param FeedColumnsMatch $feedColumnsMatch
* @return array|string
*/
public function convert($filePath, $feedColumnsMatch)
{
// if(!file_exists($filePath) ) {
// return "existe pas";
// }
// if(!is_readable($filePath)) {
// return "pas lisible";
// }
//this array will contain the elements from the file
$articles = [];
$headerRecord = [];
if($feedColumnsMatch->getFeedFormat()==="tsv" | $feedColumnsMatch->getFeedFormat()==="csv"){
if($feedColumnsMatch->getFeedFormat()==="csv"){
$delimiter = $feedColumnsMatch->getDelimiter();
}else{
$delimiter = "\t";
}
//if we can open the file on mode "read"
if (($handle = fopen($filePath, 'r')) !== FALSE) {
//represents the line we are reading
$rowCounter = 0;
//as long as there are lines
while (($rowData = fgetcsv($handle, 1000, $delimiter)) !== FALSE) {
//At first line are written the keys so we record them in $headerRecord
if(0 === $rowCounter){
$headerRecord = $rowData;
}else{ //for every other lines...
foreach ($rowData as $key => $value){ //in each line, for each value
// we set $value to the cell ($key) having the same horizontal position than $value
// but where vertical position = 0 (headerRecord[]
$articles[$rowCounter][$headerRecord[$key]]= $value;
}
}
$rowCounter++;
}
fclose($handle);
}
}
return $articles;
}
我想我错过了一步。我无法直接从 URL 读取文件,因此我必须在尝试读取文件之前先检索该文件。我该怎么做?
要从供稿 URL 下载数据,在我的例子中是一个 csv 文件, 您必须向 URL 发送请求。 Symfony 的设计目的不是向外部 URL 发送请求,因此您必须使用 cURL 或 Goutte or Guzzle。 我选择了古泽尔。以下是我的使用方法:
$client = new Client();
$response = $client->request('GET', $url);
echo "Status Code = ".$response->getStatusCode()."\n"; # 200
echo 'Content Type = '.$response->getHeaderLine('content-type')."\n";
$body = $response->getBody();
$url 是 url 我必须将请求发送到。
不要忘记在命名空间和 class 之间导入 Guzzle: 使用 GuzzleHttp\Client; .
使用此代码,您可以获得整个页面主体,即您获得的内容包含 html 标签,例如:
<!DOCTYPE html>
<html lang="en">
<body>
<pre>
Wine Directory List
<BR>
//here is the content of the csv file
</pre>
</body>
</html>
获得数据后,必须将其写入文件,以便创建
$filePath = 'public/my_data/myFile';
你 create/open 文件:
$fp = fopen($filePath, 'x');
然后你在文件中写入:
fwrite($fp, $body);
并且不要忘记关闭文件以避免内存泄漏:
fclose($fp);
最后,您只需在方便时转换文件即可。请记住,fopen() 中的模式 'x' 会创建一个文件,如果同名文件已存在,则会 returns 出错。