View source
<?php
namespace Drupal\s3fs_cors\Controller;
use Drupal\Core\Controller\ControllerBase;
use Drupal\Core\Database\Connection;
use Drupal\Core\File\FileSystemInterface;
use Drupal\Core\Logger\LoggerChannelFactoryInterface;
use Drupal\file\Entity\File;
use Drupal\s3fs\S3fsServiceInterface;
use Drupal\s3fs\StreamWrapper\S3fsStream;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\File\MimeType\MimeTypeGuesserInterface;
use Symfony\Component\HttpFoundation\JsonResponse;
class AjaxController extends ControllerBase {
protected $s3Client;
protected $database;
protected $mimeType;
protected $logger;
public function __construct(S3fsServiceInterface $s3fs, Connection $database, MimeTypeGuesserInterface $mimeType, LoggerChannelFactoryInterface $loggerFactory) {
$s3_config = $this
->config('s3fs.settings')
->get();
$this->s3Client = $s3fs
->getAmazonS3Client($s3_config);
$this->database = $database;
$this->mimeType = $mimeType;
$this->logger = $loggerFactory
->get('s3fs');
}
public static function create(ContainerInterface $container) {
return new static($container
->get('s3fs'), $container
->get('database'), $container
->get('file.mime_type.guesser'), $container
->get('logger.factory'));
}
public function getKey($directory, $file_name, $file_size, $file_index, $replace = FileSystemInterface::EXISTS_RENAME) {
$file_name = preg_replace('/[\\x00-\\x1F]/u', '_', $file_name);
if (substr(PHP_OS, 0, 3) == 'WIN') {
$file_name = str_replace([
':',
'*',
'?',
'"',
'<',
'>',
'|',
], '_', $file_name);
}
$directory = str_replace('::', '/', $directory);
$file_key = $directory . '/' . $file_name;
$file_exists = $this
->s3FileExists($file_key);
if ($file_exists) {
switch ($replace) {
case FileSystemInterface::EXISTS_REPLACE:
break;
case FileSystemInterface::EXISTS_RENAME:
$file_key = $this
->createFileKey($directory, $file_name);
break;
case FileSystemInterface::EXISTS_ERROR:
return FALSE;
}
}
return new JsonResponse([
'file_key' => $file_key,
'file_name' => $file_name,
'file_size' => $file_size,
'file_index' => $file_index,
]);
}
private function createFileKey($directory, $file_name) {
$root_folder = '';
$config = $this
->config('s3fs.settings');
if (!empty($config
->get('root_folder'))) {
$root_folder = $config
->get('root_folder') . '/';
$directory = str_replace($root_folder, '', $directory);
}
$separator = '/';
if (substr($directory, -1) == '/') {
$separator = '';
}
$base_name = substr($file_name, 0, strrpos($file_name, '.'));
$extension = substr($file_name, strrpos($file_name, '.'));
$key_base = $root_folder . $directory . $separator . $base_name;
$uri_base = 's3://' . $directory . $separator . $base_name;
$records = $this->database
->select('s3fs_file', 's')
->fields('s', [
'uri',
])
->condition('uri', $this->database
->escapeLike($uri_base) . '%', 'LIKE')
->execute()
->fetchCol();
$results = [];
foreach ($records as $record) {
$suffix = str_replace([
$uri_base,
$extension,
], '', $record);
if ($suffix) {
$suffix = (int) substr($suffix, 1);
$results[$suffix] = $record;
}
}
for ($suffix = 0; $suffix < count($results); $suffix++) {
if (!isset($results[$suffix])) {
break;
}
}
$trial_key = $key_base . '_' . $suffix . $extension;
if ($this
->s3FileExists($trial_key)) {
$this->logger
->info('S3fs cache table rebuild required (key %key missing)', [
'%key' => $trial_key,
]);
$suffix = max(array_keys($results));
do {
$trial_key = $key_base . '_' . ++$suffix . $extension;
} while ($this
->s3FileExists($trial_key));
}
return $trial_key;
}
private function s3FileExists($key) {
$config = $this
->config('s3fs.settings');
$bucket = $config
->get('bucket');
return $this->s3Client
->doesObjectExist($bucket, $key);
}
public function saveFile($file_path, $file_name, $file_size, $field_name) {
$user = $this
->currentUser();
$file_path = str_replace('::', '/', $file_path);
$config = $this
->config('s3fs.settings');
if (!empty($config
->get('root_folder'))) {
$root_folder = $config
->get('root_folder');
$file_path = str_replace($root_folder . '/', '', $file_path);
}
$file_uri = 's3://' . $file_path;
$wrapper = new S3fsStream();
$wrapper
->writeUriToCache($file_uri);
$public_folder = 's3://' . ($config
->get('public_folder') ?: 's3fs-public');
$private_folder = 's3://' . ($config
->get('private_folder') ?: 's3fs-private');
if (strpos($file_uri, $public_folder) === 0 || strpos($file_uri, $private_folder) === 0) {
$file_uri = str_replace([
$public_folder,
$private_folder,
], [
'public:/',
'private:/',
], $file_uri);
}
$file_mime = $this->mimeType
->guess($file_name);
$values = [
'uid' => $user
->id(),
'status' => 0,
'filename' => $file_name,
'uri' => $file_uri,
'filesize' => $file_size,
'filemime' => $file_mime,
'source' => $field_name,
];
$file = File::create($values);
$errors = [];
$errors = array_merge($errors, $this
->moduleHandler()
->invokeAll('file_validate', [
$file,
]));
if (empty($errors)) {
$file
->save();
$values['fid'] = $file
->id();
$values['uuid'] = $file
->uuid();
}
else {
$file
->delete();
$values['errmsg'] = implode("\n", $errors);
}
return new JsonResponse($values);
}
}