В Symfony 4 мне нужно загрузить данные с удаленного URL-адреса. Могу ли я использовать Symfony 4 или мне нужно использовать JQuery или Python или...? Нужно ли мне анализировать содержимое URL-адреса или я могу загрузить CSV-файл с URL-адреса?
Я новичок, поэтому, пожалуйста, разговаривайте со мной, как с манекеном.
Я разрабатываю веб-приложение в Symfony 4, которое должно загружать данные (через команду symfony и задачу CRON) из партнерских магазинов благодаря 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
Я видел эту тему: как скачать файл с URL-адреса с помощью javascript? Первый ответ выглядит интересно, но, как я уже сказал, я новичок и понятия не имею, как реализовать скрипт в своей команде. И я видел другие темы для Ruby или Angular: Как скачать файл с Angular2Как отображать и импортировать данные из URL-адреса фида? но мне это мало помогает...
edit: я попытался передать URL-адрес fopen, но он возвращает HTTP/1.1 403 Forbidden: доступ запрещен.
update: вот мой код на данный момент (не так много, я признаю) со всем, что я пробовал, и результатами:
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 и вставьте их в свой вопрос в виде блока кода. Этого должно быть достаточно. При необходимости укажите дополнительную информацию, например, что в этой ссылке используются символы табуляции в качестве разделителей столбцов.
@rkeet готово :) (спасибо за подсказку относительно внешних ссылок. Я только что задал свои вопросы, вишенка) Отлично, я не видел, чтобы fopen тоже работал с URL. Я попробую это. Держать вас в курсе.
Я попытался указать URL-адрес для fopen в своем классе ConverterToArray, но он отправляет мне предупреждение: fopen (myurl.com): не удалось открыть поток: HTTP-запрос не выполнен! HTTP/1.1 403 Запрещено: доступ запрещен.
Я попытался указать URL-адрес для fopen в своем классе ConverterToArray, но он отправляет мне ```` Предупреждение: fopen(myurl.com): не удалось открыть поток: HTTP-запрос не выполнен! HTTP/1.1 403 Запрещено: доступ запрещен. И то же самое с file_get_contents. Означает ли это, что удаленный веб-сайт блокирует доступ? Или может быть что-то не так в моем коде?
403 действительно означает, что доступ запрещен из-за авторизации (не аутентификации), например, «мы знаем, кто вы, но вам здесь нельзя». Однако прямой доступ к ваша оригинальная ссылка через http/s работает. Так что я думаю, что есть что-то еще на работе. Извините, я слишком устал, чтобы ясно думать, позвоните мне завтра.
@rkeet, метод без комментариев с Guzzle Client, похоже, работает. Я могу получить все данные со страницы на моей консоли. Теперь я должен записать данные в файл, и все будет сделано!!!!
Превосходно! Когда вы поняли это, не забудьте написать небольшой воспроизводимый ответ вашего решения и принять его, когда это разрешено ;-)





Чтобы загрузить данные из URL-адреса фида, в моем случае это CSV-файл, Вы должны отправить запрос на URL. Symfony не предназначен для отправки запросов на внешний URL-адрес, поэтому вам нужно использовать cURL, Гутте или Жрать. Я выбрал Гузл. Вот как я его использовал:
$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-адрес, на который я должен отправить запрос.
Не забудьте импортировать 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';
и вы создаете/открываете файл:
$fp = fopen($filePath, 'x');
Затем вы пишете в файле:
fwrite($fp, $body);
И не забудьте закрыть файл, чтобы избежать утечки памяти:
fclose($fp);
Наконец, вам просто нужно преобразовать файл в удобное для вас время. Просто помните, что режим 'x' в fopen() создает файл и возвращает ошибку, если файл с таким именем уже существует.
Пробовали ли вы использовать
file_get_contentsили, возможно, как читать csv построчно (поскольку вы можете указывать URL-адрес точного документа каждый раз, верно?)