We had a project: a catalog of 20,000 products, each requiring a main photo and a gallery of 5–8 shots. Through the Bitrix admin interface, this would have taken several man-weeks. We automated the process using the API and batch processing — the entire upload took 4 hours. The same approach works for any volume. We are a team of certified Bitrix developers with 10+ years of experience, having automated uploads for 500+ catalogs. We guarantee budget savings of 3–5 times compared to manual work. Pricing example: For a catalog of 20,000 items, you save approximately $3,000 compared to manual work.
Our mass product photo upload automation for 1C-Bitrix handles thousands of images efficiently, leveraging Bitrix image API and CommerceML integration.
Why Manual Upload via Admin Interface Is a Path to Loss
With manual upload via the "Information Blocks → Elements" interface, you have to open each product and attach a file one by one. For 20,000 products, that's 20,000 operations. Additionally, quality control is difficult: missed products, mixed-up images. Most critically, it creates uncontrolled server load: each click triggers a page reload, cache refresh, and event firing. On large catalogs, this leads to timeouts or freezes.
How We Automate the Upload
We prepare a file structure by SKU, a mapping CSV, and run a CLI script in PHP. Per the documentation, CFile manages file uploads. The code below is a basic scheme that we customize for each project (image sizes, formats, 1C integration via CommerceML).
$csvRows = parseCsv('/import/mapping.csv'); // [['xml_id' => 'sku_001', 'files' => ['main.jpg', '2.jpg']]] foreach ($csvRows as $row) { // Find element by XML_ID $element = \Bitrix\Iblock\ElementTable::getList([ 'filter' => ['XML_ID' => $row['xml_id'], 'IBLOCK_ID' => CATALOG_IBLOCK_ID], 'select' => ['ID'], ])->fetch(); if (!$element) continue; $imageDir = '/import/images/' . $row['xml_id'] . '/'; $files = []; foreach ($row['files'] as $i => $filename) { $filePath = $imageDir . $filename; if (!file_exists($filePath)) continue; $fileId = \CFile::SaveFile([ 'name' => $filename, 'type' => mime_content_type($filePath), 'tmp_name' => $filePath, 'error' => 0, 'size' => filesize($filePath), ], 'iblock'); if ($i === 0) { // First file — main image \CIBlockElement::Update($element['ID'], [ 'PREVIEW_PICTURE' => \CFile::MakeFileArray($filePath), 'DETAIL_PICTURE' => \CFile::MakeFileArray($filePath), ]); } else { $files[] = ['VALUE' => \CFile::MakeFileArray($filePath)]; } } // Multiple property for gallery if (!empty($files)) { \CIBlockElement::SetPropertyValues($element['ID'], CATALOG_IBLOCK_ID, $files, 'MORE_PHOTO'); } } CFile::MakeFileArray() does not copy the file — it's just a descriptor array. CFile::SaveFile() performs the actual save and writes to b_file.
Advanced optimization techniques include using D7 ORM queries to prefetch elements in batches, reducing database round trips. Additionally, you can leverage the Bitrix cache engine to store intermediate results, avoiding redundant file system operations.
What Technical Challenges Arise and How to Solve Them
Timeouts. Uploading 50,000 files via a web request is impossible — we use CLI scripts (php -f import.php), removing limits with set_time_limit(0) and ini_set('memory_limit', '512M').
Excessive server load due to events. By default, each CIBlockElement::Update triggers OnBeforeIBlockElementUpdate and OnAfterIBlockElementUpdate events. These can cause price recalculation, cache invalidation, and search index updates. We temporarily disable unnecessary handlers using \Bitrix\Main\EventManager::getInstance()->removeEventHandler().
Cache issues. After mass updates, the infoblock cache contains outdated file references. At the end of the import, we clear the cache using \Bitrix\Iblock\Iblock::cleanCache($iblockId) — once, not in a loop.
Error handling. We maintain a detailed log. If a file is missing or corrupted, the log records the error, and the process continues with the next product. After import, we get a report of skipped items.
Disable extra event handlers. During mass updates, OnBeforeIBlockElementUpdate and OnAfterIBlockElementUpdate can trigger heavy operations (price recalculation, cache invalidation, search update). Temporarily disable agents and events if not needed during import.
Use CLI scripts. Run via php -f import_images.php — no web request time limits.
Clear cache after completion. After mass upload, reset infoblock cache: \Bitrix\Iblock\InformationBlock::cleanTagCache($iblockId). Do this only once at the end.
Common Mistakes During Mass Upload
Error log
$log = fopen('/var/log/image_import.log', 'a'); foreach ($csvRows as $row) { try { // ... processing fwrite($log, date('Y-m-d H:i:s') . " OK: {$row['xml_id']}\n"); } catch (\Throwable $e) { fwrite($log, date('Y-m-d H:i:s') . " ERR: {$row['xml_id']} — {$e->getMessage()}\n"); } } Common errors: file not found, invalid MIME type, duplicate in b_file (Bitrix checks by hash — re-uploading the same file returns the existing ID).
Performance on Large Volumes
For a catalog of 20,000+ items, a direct loop will take 2–4 hours and may hit timeout or memory limits. Some rules:
Batch processing. Process 200–500 items per iteration, saving progress to a file or table.
Disable extra event handlers. During mass updates, OnBeforeIBlockElementUpdate and OnAfterIBlockElementUpdate can trigger heavy operations (price recalculation, cache invalidation, search update). Temporarily disable agents and events if not needed during import.
Use CLI scripts. Run via php -f import_images.php — no web request time limits.
Clear cache after completion. After mass upload, reset infoblock cache: \Bitrix\Iblock\InformationBlock::cleanTagCache($iblockId). Do this only once at the end.
Thumbnail Generation
After upload, Bitrix creates thumbnails lazily — on first access via a component. To warm the cache immediately:
\CFile::ResizeImageGet($fileId, ['width' => 400, 'height' => 400], BX_RESIZE_IMAGE_PROPORTIONAL, true); Or via a CLI utility if ImageMagick is configured on the server.
Comparison: Manual Upload vs Our Automation
| Parameter | Manual Upload | Turnkey Automation |
|---|---|---|
| Time for 10,000 items | 2-3 weeks | 2-4 hours |
| Errors | Human factor | Minimal with correct mapping |
| Server load | High (every action via admin) | Low (CLI without extra events) |
| Scalability | Only for small volumes | Up to 100,000+ without issues |
| Cost for 20,000 items | ~$4,000 | ~$1,000 |
How to Prepare Files for Upload
- Structure images in folders: each folder corresponds to a product SKU.
- Create a CSV file with columns: SKU, main image file name, set of gallery file names.
- Verify that all files are accessible at the specified paths.
- Run the CLI script that reads the CSV and uploads files via the API.
What's Included in Our Work
- Full audit of catalog structure and file storage.
- Development of a CLI script tailored to your scenario.
- Configuration of batch upload with optimization.
- Testing on a copy and final deployment.
- Documentation of the process and post-implementation support.
Estimated Timelines
| Catalog Volume | Approximate Time |
|---|---|
| Up to 1,000 items | 1–2 hours |
| 1,000–10,000 items | 4–8 hours |
| 10,000–50,000 items | 1–2 days |
Cost is calculated individually — contact us for a free estimate. Time and budget savings are guaranteed: 5–10 times faster than manual work.
Our mass product photo upload automation for 1C-Bitrix ensures reliable and fast image processing, combining CLI scripts and batch upload for any catalog size.







