mise en place de minio
This commit is contained in:
@ -9,14 +9,17 @@ use Symfony\Component\Form\Extension\Core\Type\HiddenType;
|
||||
use Symfony\Component\Filesystem\Filesystem;
|
||||
use Symfony\Component\HttpKernel\KernelInterface;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use App\Service\MinioService;
|
||||
|
||||
class CropController extends AbstractController
|
||||
{
|
||||
private $appKernel;
|
||||
private $minio;
|
||||
|
||||
public function __construct(KernelInterface $appKernel)
|
||||
public function __construct(KernelInterface $appKernel, MinioService $minio)
|
||||
{
|
||||
$this->appKernel = $appKernel;
|
||||
$this->minio = $minio;
|
||||
}
|
||||
|
||||
// Etape 01 - Téléchargement de l'image
|
||||
@ -102,6 +105,11 @@ class CropController extends AbstractController
|
||||
$data = $form->getData();
|
||||
$thumb_image_location = "uploads/$type/thumb_".$file;
|
||||
$cropped = $this->resizeThumbnailImage($thumb_image_location, $large_image_location,$data["ws"],$data["hs"],$data["xs"],$data["ys"],$scale);
|
||||
|
||||
// Dépot des fichiers sur minio
|
||||
$this->minio->upload($large_image_location,$large_image_location,true);
|
||||
$this->minio->upload($thumb_image_location,$thumb_image_location,true);
|
||||
|
||||
$submited=true;
|
||||
}
|
||||
|
||||
@ -117,32 +125,6 @@ class CropController extends AbstractController
|
||||
]);
|
||||
}
|
||||
|
||||
// Upload ckeditor
|
||||
public function ckupload(Request $request) {
|
||||
// Fichier temporaire uploadé
|
||||
$tmpfile = $request->files->get('upload');
|
||||
$extention = $tmpfile->getClientOriginalExtension();
|
||||
|
||||
// Répertoire de Destination
|
||||
$fs = new Filesystem();
|
||||
$rootdir = $this->appKernel->getProjectDir()."/public";
|
||||
$fs->mkdir($rootdir."/uploads/ckeditor");
|
||||
|
||||
// Fichier cible
|
||||
$targetName = uniqid().".".$extention;
|
||||
$targetFile = $rootdir."/uploads/ckeditor/".$targetName;
|
||||
$targetUrl = "/".$this->getParameter('appAlias')."/uploads/ckeditor/".$targetName;
|
||||
$message = "";
|
||||
|
||||
move_uploaded_file($tmpfile,$targetFile);
|
||||
|
||||
$output["uploaded"]=1;
|
||||
$output["fileName"]=$targetName;
|
||||
$output["url"]=$targetUrl;
|
||||
|
||||
return new Response(json_encode($output));
|
||||
}
|
||||
|
||||
// Calcul de la hauteur
|
||||
protected function getHeight($image) {
|
||||
$size = getimagesize($image);
|
||||
|
@ -160,10 +160,7 @@ class GroupController extends AbstractController
|
||||
|
||||
$userinfo="";
|
||||
if($data->getOwner()) {
|
||||
if(stripos($data->getOwner()->getAvatar(),"http")===0)
|
||||
$userinfo.="<img src='".$data->getOwner()->getAvatar()."' class='avatar'>";
|
||||
else
|
||||
$userinfo.="<img src='".$this->getParameter('appAlias')."uploads/avatar/".$data->getOwner()->getAvatar()."' class='avatar'>";
|
||||
$userinfo.="<img src='".$this->generateUrl('app_minio_image',["file"=>"uploads/avatar/".$data->getOwner()->getAvatar()])."' class='avatar'>";
|
||||
$userinfo.="<br>".$data->getOwner()->getUsername();
|
||||
}
|
||||
|
||||
@ -516,11 +513,7 @@ class GroupController extends AbstractController
|
||||
$action.="<a style='cursor:pointer' onClick='addUsers(".$data->getId().")'><i class='fa fa-plus fa-fw'></i></a>";
|
||||
|
||||
// Avatar
|
||||
if(stripos($data->getAvatar(),"http")===0)
|
||||
$avatar="<img src='".$data->getAvatar()."' class='avatar'>";
|
||||
else
|
||||
$avatar="<img src='".$this->getParameter('appAlias')."uploads/avatar/".$data->getAvatar()."' class='avatar'>";
|
||||
|
||||
$avatar="<img src='".$this->generateUrl('app_minio_image',["file"=>"uploads/avatar/".$data->getAvatar()])."' class='avatar'>";
|
||||
|
||||
array_push($output["data"],array("DT_RowId"=>"user".$data->getId(),$action,$avatar,$data->getUsername(),$data->getEmail(),"",""));
|
||||
}
|
||||
@ -654,10 +647,7 @@ class GroupController extends AbstractController
|
||||
$action.="<a style='cursor:pointer' onClick='delUsers(".$data->getId().")'><i class='fa fa-minus fa-fw'></i></a>";
|
||||
|
||||
// Avatar
|
||||
if(stripos($data->getAvatar(),"http")===0)
|
||||
$avatar="<img src='".$data->getAvatar()."' class='avatar'>";
|
||||
else
|
||||
$avatar="<img src='".$this->getParameter('appAlias')."uploads/avatar/".$data->getAvatar()."' class='avatar'>";
|
||||
$avatar="<img src='".$this->generateUrl('app_minio_image',["file"=>"uploads/avatar/".$data->getAvatar()])."' class='avatar'>";
|
||||
|
||||
// Flag manager
|
||||
$rolegroup="";
|
||||
|
@ -4,7 +4,7 @@ namespace App\Controller;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Filesystem\Filesystem;
|
||||
|
||||
|
||||
class HomeController extends AbstractController
|
||||
{
|
||||
@ -52,30 +52,6 @@ class HomeController extends AbstractController
|
||||
}
|
||||
|
||||
|
||||
public function upload($access,Request $request): Response
|
||||
{
|
||||
// Fichier temporaire uploadé
|
||||
$tmpfile = $request->files->get('upload');
|
||||
$extention = $tmpfile->getClientOriginalExtension();
|
||||
|
||||
// Répertoire de Destination
|
||||
$fs = new Filesystem();
|
||||
$rootdir = $this->getParameter('kernel.project_dir') . '/public';
|
||||
$fs->mkdir($rootdir."/uploads/ckeditor");
|
||||
|
||||
// Fichier cible
|
||||
$targetName = uniqid().".".$extention;
|
||||
$targetFile = $rootdir."/uploads/ckeditor/".$targetName;
|
||||
$targetUrl = $this->getParameter('appAlias')."uploads/ckeditor/".$targetName;
|
||||
$message = "";
|
||||
|
||||
move_uploaded_file($tmpfile,$targetFile);
|
||||
|
||||
$output["uploaded"]=1;
|
||||
$output["fileName"]=$targetName;
|
||||
$output["url"]=$targetUrl;
|
||||
|
||||
return new Response(json_encode($output));
|
||||
}
|
||||
|
||||
}
|
101
src/Controller/MinioController.php
Normal file
101
src/Controller/MinioController.php
Normal file
@ -0,0 +1,101 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controller;
|
||||
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use App\Service\MinioService;
|
||||
use Symfony\Component\HttpKernel\KernelInterface;
|
||||
use Symfony\Component\Filesystem\Filesystem;
|
||||
|
||||
class MinioController extends AbstractController
|
||||
{
|
||||
private $minio;
|
||||
|
||||
public function __construct(KernelInterface $appKernel, MinioService $minio)
|
||||
{
|
||||
$this->appKernel = $appKernel;
|
||||
$this->minio = $minio;
|
||||
}
|
||||
|
||||
public function ckupload($access,Request $request): Response
|
||||
{
|
||||
// Fichier temporaire uploadé
|
||||
$tmpfile = $request->files->get('upload');
|
||||
$extention = $tmpfile->getClientOriginalExtension();
|
||||
|
||||
// Répertoire de Destination
|
||||
$fs = new Filesystem();
|
||||
$rootdir = $this->getParameter('kernel.project_dir') . '/public';
|
||||
$fs->mkdir($rootdir."/uploads/ckeditor");
|
||||
|
||||
// Fichier cible
|
||||
$targetName = uniqid().".".$extention;
|
||||
$targetFile = "uploads/ckeditor/".$targetName;
|
||||
$targetUrl = $this->getParameter('appAlias')."uploads/ckeditor/".$targetName;
|
||||
$targetUrl = $this->generateUrl('app_minio_document',["file"=>"uploads/ckeditor/".$targetName]);
|
||||
$message = "";
|
||||
|
||||
//move_uploaded_file($tmpfile,$targetFile);
|
||||
$this->minio->upload($tmpfile,$targetFile,true);
|
||||
|
||||
$output["uploaded"]=1;
|
||||
$output["fileName"]=$targetName;
|
||||
$output["url"]=$targetUrl;
|
||||
|
||||
return new Response(json_encode($output));
|
||||
}
|
||||
|
||||
public function image(Request $request): Response
|
||||
{
|
||||
$file=$request->query->get("file");
|
||||
switch($file) {
|
||||
case "uploads/avatar/admin.jpg":
|
||||
case "uploads/avatar/noavatar.png":
|
||||
case "uploads/avatar/system.jpg":
|
||||
case "uploads/header/header.jpg":
|
||||
case "uploads/logo/logo.png":
|
||||
$filePath = $file;
|
||||
$content = file_get_contents($file);
|
||||
break;
|
||||
|
||||
default:
|
||||
// C'est une url = on affiche l'url
|
||||
if(stripos($file,"http")===0) {
|
||||
$filePath = $file;
|
||||
$content = file_get_contents($file);
|
||||
}
|
||||
// C'est du contenu dynamique on download depuis minio
|
||||
elseif(stripos($file,"uploads")===0) {
|
||||
$filePath = $this->minio->download($file, $file, true);
|
||||
$content = file_get_contents($filePath);
|
||||
}
|
||||
// C'est du contenu statique on download depuis minio
|
||||
else {
|
||||
$filePath = $file;
|
||||
$content = file_get_contents($file);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return new Response($content, 200, [
|
||||
'Content-Type' => mime_content_type($filePath),
|
||||
'Cache-Control' => 'max-age='.(60 * 60 * 24 * 7),
|
||||
'Expires' => gmdate(DATE_RFC1123, time() + 60 * 60 * 24 * 365),
|
||||
]);
|
||||
}
|
||||
|
||||
public function document(Request $request)
|
||||
{
|
||||
$file=$request->query->get("file");
|
||||
$filePath = $this->minio->download($file, $file, true);
|
||||
$content = file_get_contents($filePath);
|
||||
|
||||
return new Response($content, 200, [
|
||||
'Content-Type' => mime_content_type($filePath),
|
||||
'Cache-Control' => 'max-age='.(60 * 60 * 24 * 7),
|
||||
'Expires' => gmdate(DATE_RFC1123, time() + 60 * 60 * 24 * 365),
|
||||
]);
|
||||
}
|
||||
}
|
@ -22,12 +22,8 @@ class PublishController extends AbstractController
|
||||
$ret["from"]["id"]=$this->getUser()->getId();
|
||||
$ret["from"]["username"]=$this->getUser()->getUsername();
|
||||
$ret["from"]["displayname"]=$this->getUser()->getDisplayname();
|
||||
|
||||
$ret["from"]["avatar"]=$this->generateUrl('app_minio_image',["file"=>"uploads/avatar/".$this->getUser()->getAvatar()]);
|
||||
|
||||
if(stripos($this->getUser()->getAvatar(),"http")===0)
|
||||
$ret["from"]["avatar"]=$this->getUser()->getAvatar();
|
||||
else
|
||||
$ret["from"]["avatar"]=$this->getParameter('appAlias')."uploads/avatar/".$this->getUser()->getAvatar();
|
||||
|
||||
$update = new Update(
|
||||
$channel."-".$id,
|
||||
|
@ -399,8 +399,7 @@ class RestController extends AbstractFOSRestController
|
||||
$output["userposition"]=$user->getPosition();
|
||||
$output["userpostaladress"]=$user->getPostaladress();
|
||||
$output["usertelephonenumber"]=$user->getTelephonenumber();
|
||||
if(stripos($user->getAvatar(),"http")===0) $output["useravatar"]=$user->getAvatar();
|
||||
else $output["useravatar"]="https://".$this->getParameter("appWeburl").$this->getParameter("appAlias")."uploads/avatar/".$user->getAvatar();
|
||||
$output["useravatar"]="https://".str_replace("//","/",$this->getParameter("appWeburl").$this->getParameter("appAlias").$this->generateUrl('app_minio_image',["file"=>"uploads/avatar/".$user->getAvatar()],true));
|
||||
$output["userniveau01"]=$this->niveau01Format($user->getNiveau01());
|
||||
$output["userniveau02"]=$this->niveau02Format($user->getNiveau02());
|
||||
$output["usergroups"]=[];
|
||||
|
@ -255,11 +255,8 @@ class UserController extends AbstractController
|
||||
$tmp=array();
|
||||
if($access=="admin"||$access=="modo") array_push($tmp,$action);
|
||||
|
||||
if(stripos($data->getAvatar(),"http")===0)
|
||||
array_push($tmp,"<img src='".$data->getAvatar()."' class='avatar'>");
|
||||
else
|
||||
array_push($tmp,"<img src='".$this->getParameter('appAlias')."uploads/avatar/".$data->getAvatar()."' class='avatar'>");
|
||||
|
||||
array_push($tmp,"<img src='".$this->generateUrl('app_minio_image',["file"=>"uploads/avatar/".$data->getAvatar()])."' class='avatar'>");
|
||||
|
||||
array_push($tmp,$data->getUsername());
|
||||
array_push($tmp,$data->getLastname());
|
||||
array_push($tmp,$data->getFirstname());
|
||||
|
238
src/Service/MinioService.php
Normal file
238
src/Service/MinioService.php
Normal file
@ -0,0 +1,238 @@
|
||||
<?php
|
||||
|
||||
namespace App\Service;
|
||||
|
||||
use Aws\S3\Exception\S3Exception;
|
||||
use Exception;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
use Symfony\Component\Filesystem\Filesystem;
|
||||
|
||||
|
||||
class MinioService
|
||||
{
|
||||
const ERR_UNAVAILABLE = 'Service de gestion de fichiers momentanément indisponible.';
|
||||
const ERR_FILE_NOT_FOUND = 'messages.minio.404';
|
||||
protected $client;
|
||||
protected $listClient;
|
||||
protected $minioBucket;
|
||||
protected $minioRoot;
|
||||
protected $minioPathStyle;
|
||||
protected $minioSecure;
|
||||
|
||||
public function __construct($rootPath, $minioUrl, $minioKey, $minioSecret, $minioBucket, $minioRoot, $minioPathstyle, $minioSecure)
|
||||
{
|
||||
$this->rootPath = $rootPath;
|
||||
$this->minioBucket = $minioBucket;
|
||||
$this->minioPathStyle = ($minioPathstyle==1?true:false);
|
||||
$this->minioRoot = $minioRoot;
|
||||
$this->client = $this->getClient($minioUrl, $minioKey, $minioSecret, $minioPathstyle, $minioSecure);
|
||||
$this->initBucket();
|
||||
}
|
||||
|
||||
public function download(string $file, string $filename, bool $returnFile = false)
|
||||
{
|
||||
// On s'assure que le repertoire temporaire de destination existe bien
|
||||
$fs = new Filesystem();
|
||||
$tmpdir=$this->rootPath."/var/tmp";
|
||||
$fs->mkdir($tmpdir."/".dirname($filename));
|
||||
|
||||
// Approche repassant par le serveur d'appel
|
||||
try {
|
||||
$result = $this->client->getObject([
|
||||
'Bucket' => $this->minioBucket,
|
||||
'Key' => $this->minioRoot.$file,
|
||||
'SaveAs' => $tmpdir.'/'.$filename,
|
||||
]);
|
||||
} catch (S3Exception $e) {
|
||||
dump($e);
|
||||
switch ($e->getResponse()->getStatusCode()) {
|
||||
case 404:
|
||||
throw new NotFoundHttpException($this->translator->trans(self::ERR_FILE_NOT_FOUND, [], 'messages'));
|
||||
break;
|
||||
default:
|
||||
\Sentry\captureException($e);
|
||||
throw new Exception(self::ERR_UNAVAILABLE);
|
||||
break;
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
\Sentry\captureException($e);
|
||||
throw new Exception(self::ERR_UNAVAILABLE);
|
||||
}
|
||||
|
||||
if ($returnFile) {
|
||||
return $tmpdir.'/'.$filename;
|
||||
} else {
|
||||
//Suppression de la copie locale
|
||||
unlink($tmpdir.'/'.$filename);
|
||||
$res = new Response($result['Body'], 200);
|
||||
$res->headers->set('Content-Type', 'application/pdf');
|
||||
$res->headers->set('Content-Description', 'File Transfer');
|
||||
$res->headers->set('Content-Disposition', 'attachment; filename='.$filename);
|
||||
$res->headers->set('Expires', '0');
|
||||
$res->headers->set('Cache-Control', 'must-revalidate');
|
||||
$res->headers->set('Pragma', 'public');
|
||||
|
||||
return $res;
|
||||
}
|
||||
}
|
||||
|
||||
public function upload($file, $filename, $deleteSource = false)
|
||||
{
|
||||
try {
|
||||
$this->client->putObject([
|
||||
'Bucket' => $this->minioBucket,
|
||||
'Key' => $this->minioRoot.$filename,
|
||||
'SourceFile' => $file,
|
||||
]);
|
||||
} catch (Exception $e) {
|
||||
\Sentry\captureException($e);
|
||||
throw new Exception(self::ERR_UNAVAILABLE);
|
||||
}
|
||||
|
||||
if ($deleteSource) {
|
||||
unlink($file);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* move.
|
||||
*
|
||||
* @param bool $deleteSource
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function move(string $from, string $to, $deleteSource = false)
|
||||
{
|
||||
try {
|
||||
$this->client->copyObject([
|
||||
'Bucket' => $this->minioBucket,
|
||||
'Key' => $this->minioRoot.$to,
|
||||
'CopySource' => $this->minioBucket.'/'.$this->minioRoot.$from,
|
||||
]);
|
||||
} catch (Exception $e) {
|
||||
\Sentry\captureException($e);
|
||||
dump($this->minioRoot.$to);
|
||||
dump($e->getMessage());
|
||||
throw new Exception(self::ERR_UNAVAILABLE);
|
||||
}
|
||||
|
||||
if ($deleteSource) {
|
||||
$this->delete($from);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* delete.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function delete(string $file)
|
||||
{
|
||||
try {
|
||||
$this->client->deleteObject([
|
||||
'Bucket' => $this->minioBucket,
|
||||
'Key' => $this->minioRoot.$file,
|
||||
]);
|
||||
} catch (Exception $e) {
|
||||
\Sentry\captureException($e);
|
||||
throw new Exception(self::ERR_UNAVAILABLE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* countKeys.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function countKeys(string $prefix)
|
||||
{
|
||||
//On utilise un path spécifique car listObjectsV2 utilise une autre config de client
|
||||
try {
|
||||
$response = $this->client->listObjectsV2([
|
||||
'Bucket' => $this->minioBucket,
|
||||
'Prefix' => $prefix,
|
||||
]);
|
||||
|
||||
return $response->get('KeyCount');
|
||||
} catch (Exception $e) {
|
||||
\Sentry\captureException($e);
|
||||
throw new Exception(self::ERR_UNAVAILABLE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* listKeys.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function listKeys(string $prefix)
|
||||
{
|
||||
//On utilise un path spécifique car listObjectsV2 utilise une autre config de client
|
||||
try {
|
||||
$response = $this->client->listObjectsV2([
|
||||
'Bucket' => $this->minioBucket,
|
||||
'Prefix' => $prefix,
|
||||
]);
|
||||
|
||||
return $response->get('Contents');
|
||||
} catch (Exception $e) {
|
||||
\Sentry\captureException($e);
|
||||
throw new Exception(self::ERR_UNAVAILABLE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* download.
|
||||
*
|
||||
* @param string $file Nom du fichier dans minio
|
||||
* @param string $filename Nom du fichier dans la réponse
|
||||
* @param bool $returnFile Retourner un fichier ou une réponse
|
||||
*/
|
||||
|
||||
|
||||
protected function getClient($minioUrl, $minioKey, $minioSecret, bool $minioPathstyle, bool $minioSecure)
|
||||
{
|
||||
$client = new \Aws\S3\S3Client([
|
||||
'version' => 'latest',
|
||||
'region' => 'eu-west-1',
|
||||
'endpoint' => $minioUrl,
|
||||
//On force le mode DNS
|
||||
'use_path_style_endpoint' => $minioPathstyle,
|
||||
'credentials' => [
|
||||
'key' => $minioKey,
|
||||
'secret' => $minioSecret,
|
||||
],
|
||||
//On désactive les checks SSL pour le moment
|
||||
'http' => [
|
||||
'verify' => $minioSecure,
|
||||
],
|
||||
]);
|
||||
|
||||
return $client;
|
||||
}
|
||||
|
||||
protected function initBucket()
|
||||
{
|
||||
try {
|
||||
$bucketExists = false;
|
||||
|
||||
$buckets = $this->client->listBuckets()->toArray()['Buckets'];
|
||||
|
||||
foreach ($buckets as $bucket) {
|
||||
if ($this->minioBucket == $bucket['Name']) {
|
||||
$bucketExists = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$bucketExists) {
|
||||
$this->client->createBucket([
|
||||
'Bucket' => $this->minioBucket,
|
||||
]);
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
dump($e->getMessage());
|
||||
throw new Exception(self::ERR_UNAVAILABLE);
|
||||
}
|
||||
}
|
||||
}
|
@ -3,14 +3,17 @@ namespace App\Service;
|
||||
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Oneup\UploaderBundle\Event\PostPersistEvent;
|
||||
use App\Service\MinioService;
|
||||
|
||||
class UploadListener
|
||||
{
|
||||
private $em;
|
||||
private $minio;
|
||||
|
||||
public function __construct(EntityManagerInterface $em)
|
||||
public function __construct(EntityManagerInterface $em, MinioService $minio)
|
||||
{
|
||||
$this->em = $em;
|
||||
$this->minio = $minio;
|
||||
}
|
||||
|
||||
protected function getHeight($image) {
|
||||
@ -76,6 +79,15 @@ class UploadListener
|
||||
$type=$event->getType();
|
||||
|
||||
switch($type) {
|
||||
case "logo":
|
||||
$file=$event->getFile();
|
||||
$filename=$file->getFilename();
|
||||
$response = $event->getResponse();
|
||||
$response['file'] = $filename;
|
||||
|
||||
$this->minio->upload($file,"uploads/logo/".$filename,true);
|
||||
break;
|
||||
|
||||
default:
|
||||
$file=$event->getFile();
|
||||
$filename=$file->getFilename();
|
||||
|
Reference in New Issue
Block a user