✅ ЧТО СДЕЛАНО: - Поднят новый standalone OnlyOffice Document Server (порт 8083) - Настроен Nginx для доступа через office.clientright.ru:9443 - Создан open_file_v3_standalone.php для работы с новым OnlyOffice - Реализована поддержка прямых S3 URL (bucket публичный) - Добавлен s3_proxy.php с поддержкой Range requests - Создан onlyoffice_callback.php для сохранения (базовая версия) - Файлы успешно открываются и загружаются! ⚠️ TODO (на завтра): - Доработать onlyoffice_callback.php для сохранения обратно в ОРИГИНАЛЬНЫЙ путь в S3 - Добавить Redis маппинг documentKey → S3 path - Обновить CRM JS для использования open_file_v3_standalone.php - Протестировать сохранение файлов - Удалить тестовые файлы 📊 РЕЗУЛЬТАТ: - OnlyOffice Standalone РАБОТАЕТ! ✅ - Файлы открываются напрямую из S3 ✅ - Редактор загружается БЫСТРО ✅ - Автосохранение настроено ✅ (но нужна доработка callback)
238 lines
8.9 KiB
PHP
238 lines
8.9 KiB
PHP
<?php
|
||
/**
|
||
* ФИНАЛ: OnlyOffice + Pre-signed S3 URL
|
||
* Теперь с CORS и правильными настройками!
|
||
*/
|
||
|
||
require_once '/var/www/fastuser/data/www/crm.clientright.ru/crm_extensions/shared/EnvLoader.php';
|
||
EnvLoader::load('/var/www/fastuser/data/www/crm.clientright.ru/crm_extensions/.env');
|
||
|
||
error_reporting(E_ALL);
|
||
ini_set('display_errors', 1);
|
||
|
||
$fileName = isset($_GET['fileName']) ? $_GET['fileName'] : '';
|
||
|
||
if (empty($fileName)) {
|
||
die("❌ fileName не указан");
|
||
}
|
||
|
||
// Извлекаем S3 путь
|
||
$s3Path = '';
|
||
if (strpos($fileName, 'http') === 0) {
|
||
$fileName = urldecode($fileName);
|
||
$bucketId = 'f9825c87-4e3558f6-f9b6-405c-ad3d-d1535c49b61c';
|
||
$pos = strpos($fileName, $bucketId . '/');
|
||
if ($pos !== false) {
|
||
$s3Path = substr($fileName, $pos + strlen($bucketId) + 1);
|
||
}
|
||
}
|
||
|
||
if (empty($s3Path)) {
|
||
die("❌ Не удалось извлечь путь из URL");
|
||
}
|
||
|
||
// Извлекаем расширение файла
|
||
$ext = strtolower(pathinfo($s3Path, PATHINFO_EXTENSION));
|
||
|
||
// ПРЯМОЙ S3 URL (bucket публичный, CORS настроен!)
|
||
$bucket = 'f9825c87-4e3558f6-f9b6-405c-ad3d-d1535c49b61c';
|
||
$s3Url = 'https://s3.twcstorage.ru/' . $bucket . '/' . $s3Path;
|
||
|
||
// Генерируем версию и ключ документа
|
||
$version = time();
|
||
// СЛУЧАЙНЫЙ ключ при каждом запросе, чтобы OnlyOffice не использовал кеш!
|
||
$documentKey = md5($s3Path . '_' . $version);
|
||
|
||
// ПРЯМОЙ S3 URL (bucket публичный, поэтому pre-signed URL не нужен!)
|
||
// Bucket поддерживает Range requests и CORS из коробки
|
||
$fileUrl = $s3Url;
|
||
|
||
// ОТЛАДКА: Логируем все параметры
|
||
error_log("=== OPEN FILE DEBUG ===");
|
||
error_log("S3 Path: " . $s3Path);
|
||
error_log("File URL: " . $fileUrl);
|
||
error_log("File extension: " . $ext);
|
||
error_log("Document Key (unique): " . $documentKey);
|
||
error_log("Version: " . $version);
|
||
|
||
$fileBasename = basename($s3Path);
|
||
$fileType = getFileType($ext);
|
||
$officeFormats = ['doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx'];
|
||
|
||
if (!in_array($ext, $officeFormats)) {
|
||
header('Location: ' . $s3Url);
|
||
exit;
|
||
}
|
||
|
||
?>
|
||
<!DOCTYPE html>
|
||
<html>
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate">
|
||
<meta http-equiv="Pragma" content="no-cache">
|
||
<meta http-equiv="Expires" content="0">
|
||
<title><?php echo htmlspecialchars($fileBasename); ?></title>
|
||
<script src="https://office.clientright.ru:9443/web-apps/apps/api/documents/api.js?v=<?php echo time(); ?>"></script>
|
||
<style>
|
||
* { margin: 0; padding: 0; box-sizing: border-box; }
|
||
html, body {
|
||
width: 100%;
|
||
height: 100%;
|
||
overflow: hidden;
|
||
margin: 0;
|
||
padding: 0;
|
||
}
|
||
#editor {
|
||
position: absolute;
|
||
top: 0;
|
||
left: 0;
|
||
width: 100%;
|
||
height: 100%;
|
||
}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<div id="editor"></div>
|
||
|
||
<script>
|
||
// Отладка в консоль
|
||
console.log('📁 Файл:', <?php echo json_encode($fileBasename); ?>);
|
||
console.log('🔗 S3 URL:', <?php echo json_encode($fileUrl); ?>);
|
||
console.log('🔑 Document Key (unique):', <?php echo json_encode($documentKey); ?>);
|
||
console.log('✅ Standalone OnlyOffice (9443) + Direct S3 URL!');
|
||
|
||
new DocsAPI.DocEditor("editor", {
|
||
"documentType": "<?php echo $fileType; ?>",
|
||
"document": {
|
||
"fileType": "<?php echo $ext; ?>",
|
||
"key": "<?php echo $documentKey; ?>",
|
||
"title": <?php echo json_encode($fileBasename); ?>,
|
||
"url": <?php echo json_encode($fileUrl); ?>,
|
||
"permissions": {
|
||
"comment": true,
|
||
"download": true,
|
||
"edit": true,
|
||
"print": true,
|
||
"review": true
|
||
}
|
||
},
|
||
"editorConfig": {
|
||
"mode": "edit",
|
||
"lang": "ru",
|
||
"callbackUrl": "https://crm.clientright.ru/crm_extensions/file_storage/api/onlyoffice_callback.php",
|
||
"user": {
|
||
"id": "user_<?php echo $recordId ?? 'guest'; ?>",
|
||
"name": "CRM User"
|
||
},
|
||
"customization": {
|
||
"autosave": true,
|
||
"chat": false,
|
||
"comments": true,
|
||
"compactHeader": false,
|
||
"compactToolbar": false,
|
||
"help": true,
|
||
"hideRightMenu": false,
|
||
"logo": {
|
||
"image": "https://crm.clientright.ru/layouts/v7/skins/images/logo.png",
|
||
"imageEmbedded": "https://crm.clientright.ru/layouts/v7/skins/images/logo.png"
|
||
},
|
||
"zoom": 100
|
||
}
|
||
},
|
||
"height": "100%",
|
||
"width": "100%",
|
||
"type": "desktop",
|
||
"events": {
|
||
"onReady": function() {
|
||
console.log('✅ Editor ready!');
|
||
},
|
||
"onDocumentReady": function() {
|
||
console.log('✅ Document loaded!');
|
||
},
|
||
"onError": function(event) {
|
||
console.error('❌ OnlyOffice Error FULL:', JSON.stringify(event, null, 2));
|
||
console.error('Event data:', event.data);
|
||
console.error('Error code:', event.data.errorCode);
|
||
console.error('Error description:', event.data.errorDescription);
|
||
|
||
// Тестируем доступность URL из браузера
|
||
console.log('🧪 Testing S3 URL from browser...');
|
||
fetch(<?php echo json_encode($fileUrl); ?>, { method: 'HEAD' })
|
||
.then(response => {
|
||
console.log('✅ Browser can access S3:', response.status);
|
||
})
|
||
.catch(error => {
|
||
console.error('❌ Browser CANNOT access S3:', error);
|
||
});
|
||
|
||
alert('Ошибка загрузки документа:\n\n' +
|
||
'Code: ' + event.data.errorCode + '\n' +
|
||
'Description: ' + event.data.errorDescription + '\n\n' +
|
||
'Используется Pre-signed URL из S3\n\n' +
|
||
'Смотри консоль браузера (F12) для деталей!');
|
||
},
|
||
"onWarning": function(event) {
|
||
console.warn('⚠️ OnlyOffice Warning:', event);
|
||
}
|
||
}
|
||
});
|
||
</script>
|
||
</body>
|
||
</html>
|
||
<?php
|
||
|
||
function getFileType($ext) {
|
||
if (in_array($ext, ['doc', 'docx'])) return 'word';
|
||
if (in_array($ext, ['xls', 'xlsx'])) return 'cell';
|
||
if (in_array($ext, ['ppt', 'pptx'])) return 'slide';
|
||
return 'word';
|
||
}
|
||
|
||
function generatePresignedUrl($s3Key, $expirationSeconds) {
|
||
try {
|
||
require_once '/var/www/fastuser/data/www/crm.clientright.ru/vendor/autoload.php';
|
||
|
||
$s3Client = new Aws\S3\S3Client([
|
||
'version' => 'latest',
|
||
'region' => 'ru-1',
|
||
'endpoint' => 'https://s3.twcstorage.ru',
|
||
'use_path_style_endpoint' => true,
|
||
'credentials' => [
|
||
'key' => EnvLoader::getRequired('S3_ACCESS_KEY'),
|
||
'secret' => EnvLoader::getRequired('S3_SECRET_KEY')
|
||
],
|
||
'suppress_php_deprecation_warning' => true
|
||
]);
|
||
|
||
$bucket = 'f9825c87-4e3558f6-f9b6-405c-ad3d-d1535c49b61c';
|
||
|
||
// КЛЮЧ: Минимальные параметры = правильная подпись!
|
||
$cmd = $s3Client->getCommand('GetObject', [
|
||
'Bucket' => $bucket,
|
||
'Key' => $s3Key
|
||
]);
|
||
|
||
$request = $s3Client->createPresignedRequest($cmd, "+{$expirationSeconds} seconds");
|
||
return (string)$request->getUri();
|
||
|
||
} catch (Exception $e) {
|
||
error_log("Pre-signed URL error: " . $e->getMessage());
|
||
return null;
|
||
}
|
||
}
|
||
|
||
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';
|
||
}
|
||
?>
|