Как загрузить данные из URL-адреса канала csv с помощью Symfony 4?

В 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-адресу, поэтому я должен получить файл, прежде чем пытаться его прочитать. Как я могу это сделать?

Пробовали ли вы использовать file_get_contents или, возможно, как читать csv построчно (поскольку вы можете указывать URL-адрес точного документа каждый раз, верно?)

rkeet 19.06.2019 14:10

Кроме того, пожалуйста, обновите вопрос, чтобы не требовать внешних ссылок. Например, скопируйте несколько строк из URL-адреса файла CSV и вставьте их в свой вопрос в виде блока кода. Этого должно быть достаточно. При необходимости укажите дополнительную информацию, например, что в этой ссылке используются символы табуляции в качестве разделителей столбцов.

rkeet 19.06.2019 14:12

@rkeet готово :) (спасибо за подсказку относительно внешних ссылок. Я только что задал свои вопросы, вишенка) Отлично, я не видел, чтобы fopen тоже работал с URL. Я попробую это. Держать вас в курсе.

elgiorgio 19.06.2019 14:44

Я попытался указать URL-адрес для fopen в своем классе ConverterToArray, но он отправляет мне предупреждение: fopen (myurl.com): не удалось открыть поток: HTTP-запрос не выполнен! HTTP/1.1 403 Запрещено: доступ запрещен.

elgiorgio 19.06.2019 14:59

Я попытался указать URL-адрес для fopen в своем классе ConverterToArray, но он отправляет мне ```` Предупреждение: fopen(myurl.com): не удалось открыть поток: HTTP-запрос не выполнен! HTTP/1.1 403 Запрещено: доступ запрещен. И то же самое с file_get_contents. Означает ли это, что удаленный веб-сайт блокирует доступ? Или может быть что-то не так в моем коде?

elgiorgio 19.06.2019 15:27

403 действительно означает, что доступ запрещен из-за авторизации (не аутентификации), например, «мы знаем, кто вы, но вам здесь нельзя». Однако прямой доступ к ваша оригинальная ссылка через http/s работает. Так что я думаю, что есть что-то еще на работе. Извините, я слишком устал, чтобы ясно думать, позвоните мне завтра.

rkeet 19.06.2019 23:01

@rkeet, метод без комментариев с Guzzle Client, похоже, работает. Я могу получить все данные со страницы на моей консоли. Теперь я должен записать данные в файл, и все будет сделано!!!!

elgiorgio 20.06.2019 10:05

Превосходно! Когда вы поняли это, не забудьте написать небольшой воспроизводимый ответ вашего решения и принять его, когда это разрешено ;-)

rkeet 20.06.2019 12:18
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
8
863
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Чтобы загрузить данные из 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() создает файл и возвращает ошибку, если файл с таким именем уже существует.

Другие вопросы по теме