dana-medical-site/migrations/import/export_media.py
2026-10-14 13:33:13 +00:00

118 lines
4.2 KiB
Python

# -*- 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)