Реалізація перенесення медіафайлів при міграції сайту

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

Це лише деякі з технічних типів сайтів, з якими ми працюємо, і кожен із них може мати свої специфічні особливості та функціональність, а також бути адаптованим під конкретні потреби та цілі клієнта.

Пропоновані послуги
Показано 1 з 1 послугУсі 2065 послуг
Реалізація перенесення медіафайлів при міграції сайту
Середня
~2-3 робочих дні
Часті питання
Наші компетенції:
Етапи розробки
Останні роботи
  • image_website-b2b-advance_0.png
    Розробка сайту компанії B2B ADVANCE
    1262
  • image_web-applications_feedme_466_0.webp
    Розробка веб-додатків для компанії FEEDME
    1171
  • image_websites_belfingroup_462_0.webp
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    874
  • image_ecommerce_furnoro_435_0.webp
    Розробка інтернет магазину для компанії FURNORO
    1094
  • image_crm_enviok_479_0.webp
    Розробка веб-додатків для компанії Enviok
    831
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Розробка веб-сайту для компанії ФІКСПЕР
    851

Реалізація переносу медіафайлів при міграції сайту

Медіафайли — зображення, документи, відео, архіви — нерідко складають десятки гігабайтів. Перенесення потребує не тільки копіювання файлів, але й оновлення всіх посилань у контенті.

Інвентаризація медіафайлів

# Зведка по розмірам та типах
find /var/www/uploads -type f | \
  awk -F. '{print $NF}' | sort | uniq -c | sort -rn

# Загальний розмір
du -sh /var/www/uploads

# Файли без відповідності в БД (можливий мусор)
# Отримати список файлів з БД
mysql myapp -e "SELECT file_path FROM media ORDER BY file_path" > db_files.txt

# Порівняти з диском
find /uploads -type f -printf "%P\n" | sort > disk_files.txt
comm -23 disk_files.txt db_files.txt | head -50

Копіювання через rsync

# Первинна синхронізація (можна запускати кілька разів)
rsync -avz --progress \
  --checksum \
  user@old-server:/var/www/uploads/ \
  /var/www/new-site/uploads/

# З виключенням ненужних директорій
rsync -avz \
  --exclude='.git' \
  --exclude='cache/' \
  --exclude='tmp/' \
  user@old-server:/var/www/uploads/ \
  /var/www/new-site/uploads/

# Delta-синхронізація перед фінальним перемиканням
rsync -avz --delete \
  user@old-server:/var/www/uploads/ \
  /var/www/new-site/uploads/

--checksum — порівнювати за контрольною сумою, не тільки за часом зміни. --delete — видаляти файли, які відсутні на джерелі (для фінальної синхронізації).

Завантаження на S3

# Завантаження з одночасністю
aws s3 sync /var/www/uploads/ \
  s3://company-media-bucket/uploads/ \
  --storage-class STANDARD \
  --exclude "*.tmp" \
  --exclude "cache/*" \
  --acl public-read

# Перевірити кількість завантажених файлів
aws s3 ls s3://company-media-bucket/uploads/ --recursive | wc -l

Оновлення URL у контенті

Після переносу файлів посилання у контенті вказують на старі URL. Потрібно замінити всі входження:

import re
import mysql.connector

def update_media_urls_in_content(db_conn, old_base, new_base):
    cursor = db_conn.cursor()

    tables_columns = [
        ('posts', 'content'),
        ('posts', 'excerpt'),
        ('pages', 'body'),
        ('users', 'avatar_url'),
    ]

    for table, column in tables_columns:
        cursor.execute(f"SELECT id, {column} FROM {table} WHERE {column} LIKE %s",
                      (f'%{old_base}%',))
        rows = cursor.fetchall()

        for row_id, content in rows:
            if content:
                new_content = content.replace(old_base, new_base)
                cursor.execute(
                    f"UPDATE {table} SET {column} = %s WHERE id = %s",
                    (new_content, row_id)
                )

    db_conn.commit()

update_media_urls_in_content(
    db_conn,
    'https://old-site.com/wp-content/uploads',
    'https://new-site.com/uploads'
)

Для WordPress: плагін Better Search Replace або SQL:

UPDATE wp_posts
SET post_content = REPLACE(post_content,
    'https://old-site.com/wp-content/uploads/',
    'https://cdn.new-site.com/uploads/')
WHERE post_content LIKE '%old-site.com/wp-content/uploads/%';

UPDATE wp_postmeta
SET meta_value = REPLACE(meta_value,
    'https://old-site.com',
    'https://new-site.com')
WHERE meta_value LIKE '%old-site.com%';

Оптимізація при переносі

Міграція — хороший час для оптимізації зображень:

from PIL import Image
import os

def optimize_images(source_dir, target_dir):
    for root, dirs, files in os.walk(source_dir):
        for filename in files:
            if not filename.lower().endswith(('.jpg', '.jpeg', '.png')):
                continue

            source_path = os.path.join(root, filename)
            rel_path = os.path.relpath(source_path, source_dir)
            target_path = os.path.join(target_dir, rel_path)

            os.makedirs(os.path.dirname(target_path), exist_ok=True)

            img = Image.open(source_path)

            # Конвертувати в WebP
            webp_path = os.path.splitext(target_path)[0] + '.webp'
            img.save(webp_path, 'WEBP', quality=85, method=6)

            # Зберегти оригінал з оптимізацією
            img.save(target_path, optimize=True, quality=85)

Верифікація після переносу

import requests
import hashlib

def verify_file_integrity(source_server, dest_server, file_list):
    errors = []

    for path in file_list:
        src = requests.get(f"{source_server}/{path}")
        dst = requests.get(f"{dest_server}/{path}")

        if src.status_code != 200:
            errors.append(f"Source missing: {path}")
            continue
        if dst.status_code != 200:
            errors.append(f"Destination missing: {path}")
            continue

        src_hash = hashlib.md5(src.content).hexdigest()
        dst_hash = hashlib.md5(dst.content).hexdigest()

        if src_hash != dst_hash:
            errors.append(f"Checksum mismatch: {path}")

    return errors

Редиректи 301 для старих медіа URL

Якщо URL медіафайлів змінилися, налаштуйте nginx:

# Редирект старих шляхів WP
location ~* ^/wp-content/uploads/(.*)$ {
    return 301 /uploads/$1;
}

# Або через map для індивідуальних редиректів
map $uri $media_redirect {
    /wp-content/uploads/2022/01/image.jpg /uploads/2022/01/image.webp;
}

Тривалість виконання

Перенос медіафайлів з оновленням посилань у контенті для сайту обсягом до 10GB — 2–3 робочих дні.