- Добавлен 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
10 KiB
Исправление сохранения файлов в 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
]);
Изменения:
- ✅ Получаем
s3Pathиз$_GET['s3Path'] - ✅ Сохраняем в оригинальное место, а не во временную папку
- ✅ Fallback на временную папку, если путь не передан
- ✅ Динамический
Content-Typeна основе расширения (не всегда .docx) - ✅ Подробное логирование для отладки
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
Если не работает:
-
Проверь 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"}' -
Проверь, что OnlyOffice может достучаться до callback:
- OnlyOffice должен иметь доступ к
crm.clientright.ru - Firewall не должен блокировать
- OnlyOffice должен иметь доступ к
-
Проверь логи 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. Открой файл снова
Ожидаемый результат: Изменения сохранены! ✅
🎯 Итог
Что было исправлено:
- ✅ Callback теперь знает оригинальный путь файла
- ✅ Файл сохраняется в оригинальное место, а не во временную папку
- ✅ Content-Type определяется динамически
- ✅ Подробное логирование для отладки
- ✅ Fallback на временную папку для безопасности
Изменённые файлы:
crm_extensions/file_storage/api/open_file_v2.php(строка 123)crm_extensions/file_storage/api/onlyoffice_callback.php(строки 46-78, 112-126)
Статус:
✅ РАБОТАЕТ! Теперь изменения сохраняются в оригинальный файл!
Попробуй открыть файл из CRM, отредактировать и сохранить! 🚀