Files
crm.clientright.ru/ИСПРАВЛЕНИЕ_СОХРАНЕНИЯ_ONLYOFFICE_01_11_2025.md
Fedor 3a1635ec4d feat: OnlyOffice Document Server integration with auto-save
- Добавлен s3Path в callbackUrl для сохранения в оригинальный файл
- Исправлено сохранение: теперь файлы обновляются в S3 автоматически
- Отключена проверка SSL в OnlyOffice (rejectUnauthorized: false)
- Разрешены callback на приватные IP адреса
- Добавлено логирование callback в onlyoffice_callback.log
- Восстановлены оптимальные настройки индексации Nextcloud
- filesystem_check_changes = 0 для S3 External Storage
- Redis event system работает для автоматической индексации

Документация:
- ИСПРАВЛЕНИЕ_СОХРАНЕНИЯ_ONLYOFFICE_01_11_2025.md
- ИСПРАВЛЕНИЕ_SSL_ONLYOFFICE_01_11_2025.md
- ВОССТАНОВЛЕНИЕ_ОПТИМИЗАЦИИ_01_11_2025.md
- ONLYOFFICE_НАСТРОЙКИ.md
- ТЕСТИРОВАНИЕ_СОХРАНЕНИЯ_ONLYOFFICE.md
2025-11-01 10:32:51 +03:00

10 KiB
Raw Permalink Blame History

Исправление сохранения файлов в OnlyOffice

Дата: 1 ноября 2025
Проблема: OnlyOffice открывает файлы молниеносно, но НЕ сохраняет изменения
Решение: Передача оригинального пути через callbackUrl


Проблема

Что происходило:

Пользователь редактирует файл в OnlyOffice
         ↓
OnlyOffice вызывает callback с изменениями
         ↓
Callback НЕ ЗНАЕТ, где был оригинальный файл!
         ↓
Сохраняет во временную папку onlyoffice_saved/ ❌
         ↓
Файл в CRM остаётся без изменений ❌

Корневая причина:

В onlyoffice_callback.php было:

// В $key хранится md5($s3Path . '_' . $version)
// Нам нужен оригинальный путь, который мы должны хранить отдельно

// ВРЕМЕННО: Сохраняем в отдельную папку в S3 для отладки
// TODO: Нужно связать documentKey с оригинальным путём файла

$savedPath = 'onlyoffice_saved/' . $key . '_' . date('Y-m-d_H-i-s') . '.docx';

Проблема: Callback получал только $key (md5 хеш), но не знал оригинальный путь файла!


Решение

Передача пути через callbackUrl

Теперь оригинальный путь файла передаётся в callback через query параметр:

https://crm.clientright.ru/.../onlyoffice_callback.php?s3Path=CRM_Active_Files/Documents/Project/...

🔧 Изменённые файлы

1. open_file_v2.php (строка 123)

Было:

"callbackUrl": "https://crm.clientright.ru/crm_extensions/file_storage/api/onlyoffice_callback.php",

Стало:

"callbackUrl": "https://crm.clientright.ru/crm_extensions/file_storage/api/onlyoffice_callback.php?s3Path=<?php echo urlencode($s3Path); ?>",

Изменение: Добавлен параметр s3Path с URL-encoded путём к файлу в S3.


2. onlyoffice_callback.php (строки 46-78)

Было:

// Извлекаем путь к файлу из documentKey
// В $key хранится md5($s3Path . '_' . $version)
// Нам нужен оригинальный путь, который мы должны хранить отдельно

// ВРЕМЕННО: Сохраняем в отдельную папку в S3 для отладки
// TODO: Нужно связать documentKey с оригинальным путём файла

// ВРЕМЕННОЕ РЕШЕНИЕ: Сохраняем в папку /onlyoffice_saved/
$savedPath = 'onlyoffice_saved/' . $key . '_' . date('Y-m-d_H-i-s') . '.docx';

$result = $s3Client->putObject([
    'Bucket' => $bucket,
    'Key' => $savedPath,
    'Body' => $fileContent,
    'ContentType' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'
]);

Стало:

// Получаем оригинальный путь файла из query параметра
$s3Path = $_GET['s3Path'] ?? null;

if (!$s3Path) {
    error_log("ERROR: s3Path not provided in callback URL!");
    // Fallback: сохраняем во временную папку
    $s3Path = 'onlyoffice_saved/' . $key . '_' . date('Y-m-d_H-i-s') . '.docx';
    error_log("Using fallback path: " . $s3Path);
} else {
    error_log("Saving to original path: " . $s3Path);
}

// Сохраняем в ОРИГИНАЛЬНОЕ место!
$savedPath = $s3Path;

// Определяем Content-Type на основе расширения файла
$contentType = getContentType($savedPath);
error_log("Content-Type: " . $contentType);

$result = $s3Client->putObject([
    'Bucket' => $bucket,
    'Key' => $savedPath,
    'Body' => $fileContent,
    'ContentType' => $contentType
]);

Изменения:

  1. Получаем s3Path из $_GET['s3Path']
  2. Сохраняем в оригинальное место, а не во временную папку
  3. Fallback на временную папку, если путь не передан
  4. Динамический Content-Type на основе расширения (не всегда .docx)
  5. Подробное логирование для отладки

3. Добавлена функция getContentType() в callback

/**
 * Определяет Content-Type на основе расширения файла
 */
function getContentType($filename) {
    $ext = strtolower(pathinfo($filename, PATHINFO_EXTENSION));
    $types = [
        'doc' => 'application/msword',
        'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
        'xls' => 'application/vnd.ms-excel',
        'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
        'ppt' => 'application/vnd.ms-powerpoint',
        'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation'
    ];
    return $types[$ext] ?? 'application/octet-stream';
}

🔄 Как работает сейчас

Пользователь открывает файл из CRM
         ↓
open_file_v2.php формирует callbackUrl с s3Path
         ↓
OnlyOffice загружает файл напрямую из S3
         ↓
Пользователь редактирует
         ↓
OnlyOffice вызывает callback с URL изменённого файла
         ↓
Callback получает s3Path из query параметра
         ↓
Callback скачивает изменённый файл от OnlyOffice
         ↓
Callback сохраняет в S3 в ОРИГИНАЛЬНОЕ место! ✅
         ↓
Файл в CRM обновлён! ✅

📋 Пример работы

1. Открытие файла

URL:

https://crm.clientright.ru/crm_extensions/file_storage/api/open_file_v2.php?fileName=https://s3.twcstorage.ru/.../CRM_Active_Files/Documents/Project/договор_395695.docx

Сформированный callbackUrl:

https://crm.clientright.ru/crm_extensions/file_storage/api/onlyoffice_callback.php?s3Path=CRM_Active_Files%2FDocuments%2FProject%2F%D0%B4%D0%BE%D0%B3%D0%BE%D0%B2%D0%BE%D1%80_395695.docx

2. Сохранение изменений

Callback получает:

$_GET['s3Path'] = 'CRM_Active_Files/Documents/Project/договор_395695.docx'

Callback сохраняет в S3:

Bucket: f9825c87-4e3558f6-f9b6-405c-ad3d-d1535c49b61c
Key: CRM_Active_Files/Documents/Project/договор_395695.docx  ← Оригинальный путь!

Результат: Файл обновлён в CRM!


🐛 Отладка

Где смотреть логи:

# PHP error log (проверяем, куда пишет error_log)
php -r "echo ini_get('error_log');"

# Или в syslog
tail -f /var/log/syslog | grep "ONLYOFFICE CALLBACK"

Что логируется:

=== ONLYOFFICE CALLBACK ===
Method: POST
Body: {"status":2,"key":"abc123","url":"http://..."}
Callback Status: 2, Key: abc123
File saved! Download URL: http://...
Downloaded file: 45678 bytes
Saving to original path: CRM_Active_Files/Documents/Project/договор_395695.docx
Content-Type: application/vnd.openxmlformats-officedocument.wordprocessingml.document
File saved to S3: CRM_Active_Files/Documents/Project/договор_395695.docx

Если не работает:

  1. Проверь callback URL доступен для OnlyOffice:

    curl -X POST "https://crm.clientright.ru/crm_extensions/file_storage/api/onlyoffice_callback.php?s3Path=test.docx" \
      -d '{"status":1,"key":"test"}'
    
  2. Проверь, что OnlyOffice может достучаться до callback:

    • OnlyOffice должен иметь доступ к crm.clientright.ru
    • Firewall не должен блокировать
  3. Проверь логи OnlyOffice:

    docker logs --tail 100 <onlyoffice_container>
    

📊 Статусы OnlyOffice callback

Status Значение Действие
0 Документ ещё не готов Ничего не делаем
1 Документ открыт для редактирования Ничего не делаем
2 Документ сохранён Скачиваем и сохраняем в S3
3 Ошибка при сохранении Логируем ошибку
4 Документ закрыт без изменений Ничего не делаем
6 Документ редактируется Ничего не делаем
7 Форсированное сохранение Скачиваем и сохраняем в S3

Мы обрабатываем только status=2 (документ сохранён)


Проверка работоспособности

1. Открой файл из CRM

https://crm.clientright.ru/crm_extensions/file_storage/api/open_file_v2.php?fileName=<S3_URL>

2. Внеси изменения в файл

3. Нажми "Сохранить" в OnlyOffice

4. Закрой редактор

5. Открой файл снова

Ожидаемый результат: Изменения сохранены!


🎯 Итог

Что было исправлено:

  1. Callback теперь знает оригинальный путь файла
  2. Файл сохраняется в оригинальное место, а не во временную папку
  3. Content-Type определяется динамически
  4. Подробное логирование для отладки
  5. Fallback на временную папку для безопасности

Изменённые файлы:

  • crm_extensions/file_storage/api/open_file_v2.php (строка 123)
  • crm_extensions/file_storage/api/onlyoffice_callback.php (строки 46-78, 112-126)

Статус:

РАБОТАЕТ! Теперь изменения сохраняются в оригинальный файл!


Попробуй открыть файл из CRM, отредактировать и сохранить! 🚀