Files
crm.clientright.ru/crm_extensions/file_storage/S3Client.php

216 lines
7.0 KiB
PHP
Raw Normal View History

<?php
/**
* S3-Compatible Storage Client
* Клиент для работы с S3-совместимым хранилищем (TWC Storage)
*/
require_once __DIR__ . '/../vendor/autoload.php';
use Aws\S3\S3Client as AwsS3Client;
use Aws\Exception\AwsException;
class S3Client {
private $client;
private $bucket;
public function __construct($config) {
$this->bucket = $config['bucket'];
// Настройка для российского S3-совместимого хранилища
$this->client = new AwsS3Client([
'version' => $config['version'],
'region' => $config['region'],
'endpoint' => $config['endpoint'],
'use_path_style_endpoint' => $config['use_path_style_endpoint'],
'credentials' => [
'key' => $config['key'],
'secret' => $config['secret'],
],
'http' => [
'verify' => true,
]
]);
}
/**
* Загрузка файла в S3
*/
public function uploadFile($localPath, $s3Key, $options = []) {
try {
$putObjectParams = [
'Bucket' => $this->bucket,
'Key' => $s3Key,
'SourceFile' => $localPath,
];
// Добавляем ContentType если указан
if (isset($options['ContentType'])) {
$putObjectParams['ContentType'] = $options['ContentType'];
} else {
$putObjectParams['ContentType'] = $this->getMimeType($localPath);
}
// Добавляем метаданные если указаны
if (isset($options['Metadata']) && is_array($options['Metadata'])) {
// AWS SDK ожидает все значения метаданных как строки
$metadata = [];
foreach ($options['Metadata'] as $key => $value) {
$metadata[$key] = (string)$value;
}
$putObjectParams['Metadata'] = $metadata;
}
$result = $this->client->putObject($putObjectParams);
return [
'success' => true,
'url' => $this->getPublicUrl($s3Key),
's3_key' => $s3Key,
'etag' => $result['ETag']
];
} catch (AwsException $e) {
return [
'success' => false,
'error' => $e->getMessage()
];
}
}
/**
* Создание временной ссылки для скачивания
* @param string $s3Key S3 ключ файла
* @param mixed $expiresIn Время жизни URL в секундах (число) или строка типа '+10 minutes'
*/
public function getPresignedUrl($s3Key, $expiresIn = 3600) {
try {
// Преобразуем строку TTL в секунды, если нужно
if (is_string($expiresIn)) {
// Если строка начинается с '+', используем её как есть для strtotime
if (strpos($expiresIn, '+') === 0) {
$expiresIn = strtotime($expiresIn) - time();
} else {
// Иначе пытаемся распарсить как число секунд
$expiresIn = (int)$expiresIn;
}
}
// Минимум 60 секунд, максимум 7 дней
$expiresIn = max(60, min($expiresIn, 604800));
$cmd = $this->client->getCommand('GetObject', [
'Bucket' => $this->bucket,
'Key' => $s3Key
]);
$request = $this->client->createPresignedRequest($cmd, "+{$expiresIn} seconds");
return [
'success' => true,
'url' => (string) $request->getUri()
];
} catch (AwsException $e) {
return [
'success' => false,
'error' => $e->getMessage(),
'error_code' => $e->getAwsErrorCode(),
'request_id' => $e->getAwsRequestId()
];
}
}
/**
* Удаление файла из S3
*/
public function deleteObject($s3Key) {
try {
$result = $this->client->deleteObject([
'Bucket' => $this->bucket,
'Key' => $s3Key
]);
return [
'success' => true,
'deleted_key' => $s3Key
];
} catch (AwsException $e) {
return [
'success' => false,
'error' => $e->getMessage()
];
}
}
/**
* Скачивание файла во временную папку
*/
public function downloadToTemp($s3Key) {
$tempFile = sys_get_temp_dir() . '/' . uniqid('s3_download_') . '_' . basename($s3Key);
try {
$this->client->getObject([
'Bucket' => $this->bucket,
'Key' => $s3Key,
'SaveAs' => $tempFile
]);
return $tempFile;
} catch (AwsException $e) {
throw new Exception('S3 download failed: ' . $e->getMessage());
}
}
/**
* Проверка существования файла
*/
public function fileExists($s3Key) {
try {
$this->client->headObject([
'Bucket' => $this->bucket,
'Key' => $s3Key
]);
return true;
} catch (AwsException $e) {
return false;
}
}
/**
* Получение публичного URL
*/
private function getPublicUrl($s3Key) {
return $this->client->getObjectUrl($this->bucket, $s3Key);
}
/**
* Определение MIME типа файла
*/
private function getMimeType($filePath) {
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mimeType = finfo_file($finfo, $filePath);
finfo_close($finfo);
return $mimeType ?: 'application/octet-stream';
}
/**
* Генерация ключа для S3 на основе CRM данных
*/
public function generateS3Key($crmData, $isNewVersion = false) {
$module = $crmData['module'] ?? 'Documents';
$recordId = $crmData['record_id'] ?? 'unknown';
$fileName = $crmData['file_name'] ?? 'file';
$basePath = strtolower($module) . '/' . $recordId;
if ($isNewVersion) {
$timestamp = date('Y-m-d_H-i-s');
$fileName = pathinfo($fileName, PATHINFO_FILENAME) . '_v' . $timestamp . '.' . pathinfo($fileName, PATHINFO_EXTENSION);
}
return $basePath . '/' . $fileName;
}
}