Реализация импорта данных (CSV/Excel/XML) в веб-приложение

Наша компания занимается разработкой, поддержкой и обслуживанием сайтов любой сложности. От простых одностраничных сайтов до масштабных кластерных систем построенных на микро сервисах. Опыт разработчиков подтвержден сертификатами от вендоров.
Разработка и обслуживание любых видов сайтов:
Информационные сайты или веб-приложения
Сайты визитки, landing page, корпоративные сайты, онлайн каталоги, квиз, промо-сайты, блоги, новостные ресурсы, информационные порталы, форумы, агрегаторы
Сайты или веб-приложения электронной коммерции
Интернет-магазины, B2B-порталы, маркетплейсы, онлайн-обменники, кэшбэк-сайты, биржи, дропшиппинг-платформы, парсеры товаров
Веб-приложения для управления бизнес-процессами
CRM-системы, ERP-системы, корпоративные порталы, системы управления производством, парсеры информации
Сайты или веб-приложения электронных услуг
Доски объявлений, онлайн-школы, онлайн-кинотеатры, конструкторы сайтов, порталы предоставления электронных услуг, видеохостинги, тематические порталы

Это лишь некоторые из технических типов сайтов, с которыми мы работаем, и каждый из них может иметь свои специфические особенности и функциональность, а также быть адаптированным под конкретные потребности и цели клиента

Предлагаемые услуги
Показано 1 из 1 услугВсе 2065 услуг
Реализация импорта данных (CSV/Excel/XML) в веб-приложение
Средняя
~5 рабочих дней
Часто задаваемые вопросы
Наши компетенции:
Этапы разработки
Последние работы
  • image_website-b2b-advance_0.png
    Разработка сайта компании B2B ADVANCE
    1214
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1161
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    852
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1041
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    823
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Разработка веб-сайта для компании ФИКСПЕР
    815

Реализация импорта данных CSV, Excel, XML

Импорт данных обрабатывает загруженные файлы: валидирует структуру, трансформирует строки, пакетно сохраняет в БД. Для больших файлов — чтение по частям в фоне.

Laravel: импорт через Laravel Excel

// Импорт пользователей из CSV/Excel
class UsersImport implements ToModel, WithHeadingRow, WithValidation, SkipsOnError
{
    use Importable, SkipsErrors;

    private int $imported = 0;
    private int $failed   = 0;

    public function model(array $row): ?User
    {
        $this->imported++;

        return User::firstOrCreate(
            ['email' => $row['email']],
            [
                'name'     => $row['name'],
                'phone'    => $row['phone'] ?? null,
                'password' => bcrypt(Str::random(16)),
            ]
        );
    }

    public function rules(): array
    {
        return [
            'email' => 'required|email',
            'name'  => 'required|string|max:255',
            'phone' => 'nullable|string|max:20',
        ];
    }

    public function customValidationMessages(): array
    {
        return [
            'email.required' => 'Колонка email обязательна',
            'email.email'    => 'Некорректный формат email в строке :attribute',
        ];
    }

    public function onError(\Throwable $e): void
    {
        $this->failed++;
        Log::warning('Import row failed', ['error' => $e->getMessage()]);
    }

    public function getStats(): array
    {
        return ['imported' => $this->imported, 'failed' => $this->failed];
    }
}

// Controller
class ImportController extends Controller
{
    public function store(Request $request): JsonResponse
    {
        $request->validate([
            'file' => 'required|file|mimes:csv,xlsx,xls|max:10240',
        ]);

        $import = new UsersImport();

        Excel::import($import, $request->file('file'));

        return response()->json([
            'message'  => 'Импорт завершён',
            'stats'    => $import->getStats(),
            'errors'   => $import->errors()->map(fn($e) => $e->getMessage()),
        ]);
    }
}

Чанковый импорт для больших файлов

class LargeProductsImport implements ToModel, WithChunkReading, WithHeadingRow
{
    public function chunkSize(): int
    {
        return 500;
    }

    public function model(array $row): Product
    {
        return new Product([
            'sku'         => $row['sku'],
            'name'        => $row['name'],
            'price'       => (float) str_replace(',', '.', $row['price']),
            'stock'       => (int) $row['stock'],
            'category_id' => Category::getIdByName($row['category']),
        ]);
    }
}

// Асинхронно в очереди
Excel::queueImport(new LargeProductsImport(), $request->file('file'));

Node.js: CSV парсинг

import { parse } from 'csv-parse';
import { createReadStream } from 'fs';
import { pipeline } from 'stream/promises';

interface UserRow {
  email: string;
  name: string;
  phone?: string;
}

async function importUsersFromCsv(filePath: string): Promise<{ imported: number; failed: number }> {
  let imported = 0;
  let failed = 0;
  const batch: UserRow[] = [];
  const BATCH_SIZE = 100;

  const parser = parse({
    columns: true,         // первая строка — заголовки
    skip_empty_lines: true,
    trim: true,
    delimiter: [',', ';'], // автоопределение разделителя
    bom: true,             // убрать UTF-8 BOM
  });

  const processBatch = async () => {
    if (batch.length === 0) return;

    const rows = [...batch];
    batch.length = 0;

    try {
      await db.user.createMany({
        data: rows.map(row => ({
          email: row.email.toLowerCase(),
          name: row.name,
          phone: row.phone || null,
        })),
        skipDuplicates: true,
      });
      imported += rows.length;
    } catch (err) {
      failed += rows.length;
      console.error('Batch insert failed:', err);
    }
  };

  for await (const record of createReadStream(filePath).pipe(parser)) {
    if (!record.email || !record.name) {
      failed++;
      continue;
    }
    batch.push(record);
    if (batch.length >= BATCH_SIZE) await processBatch();
  }

  await processBatch();  // последний неполный батч

  return { imported, failed };
}

XML импорт (прайс-листы, B2B)

class XmlPriceImport
{
    public function import(string $filePath): array
    {
        $xml = simplexml_load_file($filePath, 'SimpleXMLElement', LIBXML_NOCDATA);

        if ($xml === false) {
            throw new \InvalidArgumentException('Некорректный XML файл');
        }

        $products = [];

        foreach ($xml->offers->offer as $offer) {
            $products[] = [
                'sku'   => (string) $offer['id'],
                'name'  => (string) $offer->name,
                'price' => (float) $offer->price,
                'url'   => (string) $offer->url,
            ];
        }

        // Пакетное обновление
        foreach (array_chunk($products, 200) as $chunk) {
            Product::upsert($chunk, ['sku'], ['name', 'price', 'url']);
        }

        return ['total' => count($products)];
    }
}

Валидация и отчёт об ошибках

Хороший импорт сообщает пользователю конкретно какие строки не прошли и почему:

// Возврат детального отчёта
return response()->json([
    'total'    => $total,
    'imported' => $imported,
    'failed'   => $failed,
    'errors'   => [
        ['row' => 3, 'field' => 'email', 'message' => 'Некорректный email: not-an-email'],
        ['row' => 7, 'field' => 'price', 'message' => 'Цена должна быть числом'],
    ],
]);

Срок реализации

CSV/Excel импорт с валидацией для Laravel или Node.js: 2–3 дня. С чанковой обработкой, детальным отчётом об ошибках и XML поддержкой: 3–5 дней.