# -*- coding: utf-8 -*- """Переносит картинки из архива Bitrix в media/ нового проекта и генерит seed_media.sql.""" import sqlread, io, os, zipfile P = 'db.sql' ZIP = r'C:\Users\naym4\Downloads\public_html.zip' MEDIA_DIR = r'D:\dana\media' OUT = io.open('seed_media.sql', 'w', encoding='utf-8') MIME = {'.jpg': 'image/jpeg', '.jpeg': 'image/jpeg', '.png': 'image/png', '.gif': 'image/gif', '.svg': 'image/svg+xml', '.webp': 'image/webp', '.pdf': 'application/pdf'} def esc(s): return "'" + str(s or '').replace("\\", "\\\\").replace("'", "''") + "'" # --- b_file: id -> (subdir, name, ctype, size, w, h, original) --- files = {} for r in sqlread.rows(P, 'b_file'): files[r['ID']] = r # --- свойство ICON (344) услуг: element_id -> file_id --- icon_of = {} for r in sqlread.rows(P, 'b_iblock_element_property'): if r.get('IBLOCK_PROPERTY_ID') == '344' and r.get('VALUE'): icon_of[r['IBLOCK_ELEMENT_ID']] = r['VALUE'] # какие элементы каких инфоблоков и какое поле-картинка использовать # (iblock, поле-приоритет, целевая таблица, целевая колонка) PLAN = [ ('29', ['PREVIEW_PICTURE', 'DETAIL_PICTURE'], 'doctors', 'photo_id'), ('30', ['PREVIEW_PICTURE', 'DETAIL_PICTURE'], 'services', 'image_id'), ('50', ['PREVIEW_PICTURE', 'DETAIL_PICTURE'], 'checkups', 'image_id'), ] zf = zipfile.ZipFile(ZIP) zip_names = set(zf.namelist()) extracted = {} # file_id -> web path skipped = 0 def ensure(file_id): """Извлечь файл из архива, вернуть web-путь или None.""" if file_id in extracted: return extracted[file_id] f = files.get(file_id) if not f: return None subdir = (f.get('SUBDIR') or '').strip() name = (f.get('FILE_NAME') or '').strip() if not subdir or not name: return None arc = 'public_html/upload/%s/%s' % (subdir, name) if arc not in zip_names: return None dest_dir = os.path.join(MEDIA_DIR, subdir.replace('/', os.sep)) os.makedirs(dest_dir, exist_ok=True) with zf.open(arc) as src, open(os.path.join(dest_dir, name), 'wb') as dst: dst.write(src.read()) web = '/media/%s/%s' % (subdir, name) extracted[file_id] = web return web OUT.write('-- Картинки из архива Bitrix. Пути ссылаются на файлы в D:\\dana\\media\n') OUT.write('BEGIN;\n\n') def emit_media(file_id, web, alt): f = files[file_id] ext = os.path.splitext(web)[1].lower() mime = MIME.get(ext, f.get('CONTENT_TYPE') or 'application/octet-stream') if mime == 'application/octet-stream' and ext in MIME: mime = MIME[ext] w = f.get('WIDTH') or '0' h = f.get('HEIGHT') or '0' size = f.get('FILE_SIZE') or '0' OUT.write( "INSERT INTO media (path, mime, size, width, height, alt) VALUES (%s,%s,%s,%s,%s,%s) " "ON CONFLICT (path) DO NOTHING;\n" % ( esc(web), esc(mime), size, w if w != '' else '0', h if h != '' else '0', esc(alt))) count = {} for ibid, fields, table, col in PLAN: c = 0 for r in sqlread.rows(P, 'b_iblock_element'): if r['IBLOCK_ID'] != ibid or r.get('ACTIVE') != 'Y': continue fid = None for fld in fields: if r.get(fld) and r[fld] in files: fid = r[fld] break if not fid: continue web = ensure(fid) if not web: continue alt = (r.get('NAME') or '').strip() emit_media(fid, web, alt) OUT.write( "UPDATE %s SET %s = (SELECT id FROM media WHERE path=%s) WHERE legacy_id=%s;\n" % ( table, col, esc(web), r['ID'])) c += 1 count[table] = c # --- SVG-иконки услуг --- icons = 0 for eid, fid in icon_of.items(): web = ensure(fid) if not web: continue emit_media(fid, web, '') OUT.write("UPDATE services SET icon = %s WHERE legacy_id=%s;\n" % (esc(web), eid)) icons += 1 OUT.write('\nCOMMIT;\n') OUT.close() print('extracted files:', len(extracted)) print('links:', count, 'icons:', icons)