Pobieranie plików z CSV w node.js

W tym wpisie pokaże jak wczytać i przetworzyć dane z pliku CSV za pomocą skryptu w node.js. Nasz przykładowy plik zawiera URL do obrazków. Spróbujmy wczytać CSV i zapisać wszystkie obrazki do lokalnego katalogu.

screen z gist github, pliki CSC z nazwą kota i linkiem oraz plik wykonawczy index.js

Setup

Utwórz nowy katalog, zainstaluj paczkę csv-parser, utwórz plik index.js

mkdir csv-script && cd csv-script
yarn init # or npm init
yarn add csv-parser # or npm install csv-parser
touch index.js

Skrypt

const fs = require('fs');
const http = require('http');
const https = require('https');
const csv = require('csv-parser'); // yarn add csv-parser
const { resolve } = require('path');

const filename = 'catsDB.csv';
const directory = './data';
let i = 0;

fs.createReadStream(filename)
    .pipe(csv())
    .on('data', function (data) {
        // console.log(data) /* Check CSV row structure */
        try {
            console.log(`Row ${i}: ${data.name}: ${data.url}`)
            download(data.url, `${directory}/${i}-${data.name}.jpg`)
                .then(resolve => console.log(`SAVE in ${resolve.path}`))
            i++;
        }
        catch (err) {
            console.error(err)
        }
    })
    .on('end', () => {
        console.log('> Finish read CSV')
    });

const download = (url, filePath, cb) => {

    if (!url || (url && url.indexOf('http') == -1)) {
        return;
    }
    const protocol = !url.charAt(4).localeCompare('s') ? https : http;

    // Create directory if not exist
    if (!fs.existsSync(directory)) {
        fs.mkdirSync(directory);
    }

    const file = fs.createWriteStream(filePath);
    return new Promise((resolve, reject) => {
        const request = protocol.get(url, (response) => {
            if (response.statusCode !== 200) {
                reject(new Error(`Failed to get '${url}' (${response.statusCode})`));
                return;
            }

            response.pipe(file);
            file.on('finish', () => resolve(file))
                .on('error', (err) => {
                    fs.unlink(filePath, () => reject(err));
                });
        }).on('error', (err) => {
            fs.unlink(filePath, () => reject(err));
        });

        request.end();
    })
};

Wczytanie i przetwarzanie CSV

Otwieramy strumień czytania danych fs.createReadStream.

Nasz middleware czyli csv-parser powinien przetworzyć plik CSV. Wiersze to obiekty, atrybutami są nazwy kolumn.
Wyświetl obiekt w konsoli lub podejrzyj w trybie debugowania twoją strukturę CSV, pamiętaj żeby zwalidować dane 🧹.

fs.createReadStream(filename)
    .pipe(csv())
    .on('data', function (data) {
        console.log(data) /* Check CSV row structure */
        try {
            console.log(`Row ${i}: ${data.name}: ${data.url}`)
            download(data.url, `${directory}/${i}-${data.name}.jpg`)
                .then(resolve => console.log(`SAVE in ${resolve.path}`))
            i++;
        }
        catch (err) {
            console.error(err)
        }
    })
    .on('end', () => {
        console.log('> Finish read CSV')
    });

Pobranie i zapisanie plików

Załóżmy że chcemy pobrać pliki wskazane w pliku CSV jako adres URL. Napiszmy funkcję która pobierze plik i zapisze go w naszym lokalnym systemie plików. Utwórzmy funkcję download na wejściu dostaje ona parametry:

  • url (String) – adres do zasobu
  • filePath (String) – nazwa i ścieżka docelowego pliku do zapisu na dysku
  1. Walidacja. Na początku możemy sprawdzić dane na wypadek braku lub błędnych wartości.
  2. Wybór protokołu na podstawie URL.
  3. Stworzenie katalogu jeśli nie istnieje.
  4. Utworzenie strumienia do zapisu pliku.
  5. Zapytanie GET do zasobu jako promis
  6. Sprawdzenie kodu odpowiedzi
  7. Zwrócenie Resolve/Reject w promise
  8. Zamkniecie połączenia
const download = (url, filePath) => {

    if (!url || (url && url.indexOf('http') == -1)) {
        return;
    }
    const protocol = !url.charAt(4).localeCompare('s') ? https : http;

    // Create directory if not exist
    if (!fs.existsSync(directory)) {
        fs.mkdirSync(directory);
    }

    const file = fs.createWriteStream(filePath);
    return new Promise((resolve, reject) => {
        const request = protocol.get(url, (response) => {
            if (response.statusCode !== 200) {
                reject(new Error(`Failed to get '${url}' (${response.statusCode})`));
                return;
            }

            response.pipe(file);
            file.on('finish', () => resolve(file))
                .on('error', (err) => {
                    fs.unlink(filePath, () => reject(err));
                });
        }).on('error', (err) => {
            fs.unlink(filePath, () => reject(err));
        });

        request.end();
    })
};

Uruchomienie

Program uruchamiamy node <NAZWA_SKRYPTU> lub node .

Po odpaleniu skryptu powinien utworzyć się katalog data zawierający zdjęcia kotków 🐈.

Podsumowanie

Node.js tak jak Python i Bash może posłużyć pisaniu prostych skryptów do przetwarzania plików, i zadań systemowych (CRON, wyszukiwanie, automatyzacja etc.). Powyższy wpis jest przykładem przetwarzania danych z plików CSV,

Gdy mamy skorzystać z danych w postaci plików CSV, excel, gDocs możemy zautomatyzować pracę np. przetwarzanie danych, tworzenie statystyk, parsowanie do innej struktury, skrypty cron…

Kod źródłowy (gist): https://gist.github.com/Dyzio18/b265968e11c8c88b3c8ddb006e7bb1dc

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany.

Scroll to top