ldc-dam/app/Http/Controllers/UploadController.php

550 lines
24 KiB
PHP
Raw Normal View History

2019-05-29 14:05:54 +02:00
<?php
2022-04-19 16:07:27 +02:00
2019-05-29 14:05:54 +02:00
namespace App\Http\Controllers;
2022-04-20 15:23:31 +02:00
use App\Http\Traits\MediaTools;
use App\Models\Historique;
use App\Models\Media;
use App\Models\Site;
use Illuminate\Http\Request;
2019-05-29 14:05:54 +02:00
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Log;
2019-05-29 14:05:54 +02:00
use Illuminate\Support\Facades\Storage;
2022-04-20 15:23:31 +02:00
use Illuminate\Support\Str;
2019-05-29 14:05:54 +02:00
2021-06-01 17:11:27 +02:00
class UploadController extends Controller
{
use MediaTools;
public function index(Request $request)
{
// ---- Vérification du token de sécurité
$token = $request->get('token');
2022-04-19 16:07:27 +02:00
if ($token != env('TOKEN_DEPOT', "c8c4613a-236c-4b06-95f6-a9c9c6c18861")) {
return abort(404);
2021-06-01 17:11:27 +02:00
}
$sites = Site::orderBy('libelle')->get();
return view('upload.show')->with(
[
2022-04-19 16:07:27 +02:00
'sites' => $sites,
2021-06-01 17:11:27 +02:00
]
);
}
public function storeMedia(Request $request)
{
2022-04-19 16:07:27 +02:00
$uid = $request->input('uid');
$sujet_id = $request->input('sujet_id');
$dossier_id = $request->input('dossier_id');
2021-06-01 17:11:27 +02:00
$replaceMediaId = $request->input('replaceMediaId');
2022-04-19 16:07:27 +02:00
if ($dossier_id == 0) {
$dossier_id = null;
2021-06-01 17:11:27 +02:00
}
2022-04-19 16:07:27 +02:00
$headers = $request->headers->all();
2021-06-01 17:11:27 +02:00
$acceptFileTypes = array('gif','jpeg', 'jpg','png','mp4','mp3','psd','ai','svg','pdf');
if ($request->hasFile('files')) {
$filesa = [];
2022-04-20 15:23:31 +02:00
/** @var array<\Illuminate\Http\UploadedFile> */
$files = $request->file('files');
2021-06-01 17:11:27 +02:00
2022-04-20 15:23:31 +02:00
foreach ($files as $file) {
2022-04-19 16:07:27 +02:00
$is_last_chunk = false;
2021-06-01 17:11:27 +02:00
$is_chunked_upload = !empty($headers['content-range']);
if ($is_chunked_upload) {
if (preg_match('|(\d+)/(\d+)|', $headers['content-range'][0], $range)) {
if ($range[1] == $range[2] - 1) {
$is_last_chunk = true;
}
}
}
2022-04-20 15:23:31 +02:00
$extension = strtolower($file->getClientOriginalExtension());
$originalName = str_replace("." . $extension, "", $file->getClientOriginalName());
2022-04-19 16:07:27 +02:00
if (!in_array($extension, $acceptFileTypes)) {
return array("false");
2021-06-01 17:11:27 +02:00
}
2022-04-19 16:07:27 +02:00
if ($is_chunked_upload) {
$filename = $uid . "_" . $range[1] . "." . $extension;
} else {
$filename = $uid . '.' . $extension;
2021-06-01 17:11:27 +02:00
}
$uploadPath = public_path() . '/uploads/';
2022-04-20 15:23:31 +02:00
$file->move($uploadPath, $filename);
2021-06-01 17:11:27 +02:00
2022-04-20 15:23:31 +02:00
// * si c'est le dernier morceux d'un fichier
2022-04-19 16:07:27 +02:00
if ($is_last_chunk) {
if ($dossier = opendir($uploadPath)) {
2021-06-01 17:11:27 +02:00
$dirFiles = array();
2022-04-20 15:23:31 +02:00
// * on compile tous les chunk du fichier
2022-04-19 16:07:27 +02:00
while (false !== ($fichier = readdir($dossier))) {
if ($fichier != '.' && $fichier != '..') {
if (strpos($fichier, $uid) !== false) {
2022-04-20 15:23:31 +02:00
$dirFiles[$fichier] = str_replace(
".{$extension}",
"",
str_replace("{$uid}_", "", $fichier)
);
2021-06-01 17:11:27 +02:00
}
}
}
closedir($dossier);
2022-04-20 15:23:31 +02:00
// * on les trie pour les assembler dans le bon ordre
2021-06-01 17:11:27 +02:00
asort($dirFiles, SORT_NUMERIC);
2022-04-20 15:23:31 +02:00
// * on les assemble dans un fichier final
2021-06-01 17:11:27 +02:00
$filename = $uid . '.' . $extension;
2022-04-19 16:07:27 +02:00
foreach ($dirFiles as $key => $fichier) {
$file = fopen($uploadPath . $key, 'rb');
$buff = fread($file, filesize($uploadPath . $key));
2021-06-01 17:11:27 +02:00
fclose($file);
2022-04-19 16:07:27 +02:00
$final = fopen($uploadPath . $filename, 'a');
2021-06-01 17:11:27 +02:00
$write = fwrite($final, $buff);
fclose($final);
2022-04-19 16:07:27 +02:00
unlink($uploadPath . $key);
2021-06-01 17:11:27 +02:00
}
2022-04-19 16:07:27 +02:00
}//end if
}//end if
2021-06-01 17:11:27 +02:00
2022-04-20 15:23:31 +02:00
// * si c'est le dernier morceau d'un fichier ou que c'est un envoi simple
2022-04-19 16:07:27 +02:00
if ($is_last_chunk || !$is_chunked_upload) {
$destinationPath = $this->getMediaFolder() . "/";
2021-06-01 17:11:27 +02:00
2022-04-20 15:23:31 +02:00
// * si on upload un média pour remplacer un fichier par un autre
2022-04-19 16:07:27 +02:00
if ($replaceMediaId != 0) {
2022-04-20 15:23:31 +02:00
// * on récupère le média à modifier
2022-04-19 16:07:27 +02:00
/** @var \App\Models\Media|null */
$media = Media::where('id', $replaceMediaId)->first();
2021-06-01 17:11:27 +02:00
2022-04-20 15:23:31 +02:00
// * On déplace le fichier dans le répertoire des médias
if (!Storage::move("uploads/{$filename}", $destinationPath . $filename)) {
throw new \ErrorException(
"Could not move uploaded file $filename into {$destinationPath}{$filename}"
);
}
2021-06-01 17:11:27 +02:00
2022-04-20 15:23:31 +02:00
// * supprime les fichiers médias stockés sur disque
2022-04-19 16:07:27 +02:00
$filesfF = Storage::files($media->folder . "/");
$filepath = preg_quote($media->folder . $media->uid, '/');
$matchingFiles = preg_grep('/^' . $filepath . '/', $filesfF);
2021-06-01 17:11:27 +02:00
Storage::delete($matchingFiles);
$media->isDefault = 0;
$media->save();
2022-04-19 16:07:27 +02:00
} else {
2022-04-20 15:23:31 +02:00
// * On déplace le fichier dans le répertoire des médias
if (!Storage::move("uploads/{$filename}", $destinationPath . $filename)) {
throw new \ErrorException(
"Could not move uploaded file $filename into {$destinationPath}{$filename}"
);
}
2021-06-01 17:11:27 +02:00
2022-04-20 15:23:31 +02:00
// * on créé un média en bdd
2022-04-19 16:07:27 +02:00
$media = new Media();
2021-06-01 17:11:27 +02:00
$media->dossier_id = $dossier_id;
2022-04-19 16:07:27 +02:00
$media->sujet_id = $sujet_id;
2022-04-20 15:23:31 +02:00
// * Par défaut FR
$media->langue_id = 1;
2022-04-20 15:23:31 +02:00
// * Par défaut propriété de la marque
$media->copyright_id = 3;
2022-04-19 16:07:27 +02:00
}//end if
2021-06-01 17:11:27 +02:00
$media->extension = $extension;
2022-04-19 16:07:27 +02:00
$media->folder = $destinationPath;
if ($replaceMediaId == 0) {
$media->libelle = mb_substr($originalName, 0, 50, "UTF-8");
$media->created_by = Auth::user()->id;
2021-06-01 17:11:27 +02:00
}
2022-04-19 16:07:27 +02:00
$media->uid = $uid;
2022-04-20 15:23:31 +02:00
$media->taille = $this->formatBytes(Storage::size($destinationPath . $filename));
2021-06-01 17:11:27 +02:00
switch ($extension) {
2022-04-20 15:23:31 +02:00
// * Photo (1)
2022-04-19 16:07:27 +02:00
case 'gif':
case 'jpeg':
case 'jpg':
case 'png':
case 'ai':
case 'pdf':
case 'psd':
$media->typemedia_id = 1;
2022-04-20 15:23:31 +02:00
$im = new \Imagick($destinationPath . $filename);
2022-04-19 16:07:27 +02:00
if (in_array($extension, array("pdf", "ai", "psd", "gif"))) {
$im->setIteratorIndex(0);
}
2021-06-01 17:11:27 +02:00
2022-04-19 16:07:27 +02:00
$resolutions = $im->getImageResolution();
$media->resolution = round($resolutions['x'] * 2.54);
$imageprops = $im->getImageGeometry();
$media->largeur = $imageprops['width'];
$media->hauteur = $imageprops['height'];
if ($media->resolution != 0) {
$media->largeur_mm = ceil(($media->largeur * 2.54 / $media->resolution) * 10);
$media->hauteur_mm = ceil(($media->hauteur * 2.54 / $media->resolution) * 10);
} else {
$media->largeur_mm = "";
$media->hauteur_mm = "";
}
$media->save();
$im->destroy();
// ---- Creation des vignettes de base
$this->createSysThumb($media);
// ---- Creation des vignettes en lien avec le sujet du média
if (isset($sujet_id)) {
$this->createThumb($media);
}
break;
2022-04-20 15:23:31 +02:00
// * Illustration/Vectorielle (2)
2022-04-19 16:07:27 +02:00
case 'svg':
$media->typemedia_id = 2;
$media->save();
break;
2022-04-20 15:23:31 +02:00
// * Vidéo (3)
2022-04-19 16:07:27 +02:00
case 'mp4':
$media->typemedia_id = 3;
$getID3 = new \getID3();
if ($fileInfo = $getID3->analyze($destinationPath . $filename)) {
$media->largeur = $fileInfo['video']['resolution_x'];
$media->hauteur = $fileInfo['video']['resolution_y'];
$media->duree = $fileInfo['playtime_string'];
}
$media->save();
break;
2022-04-20 15:23:31 +02:00
// * Audio (4)
2022-04-19 16:07:27 +02:00
case 'mp3':
$media->typemedia_id = 4;
$getID3 = new \getID3();
if ($fileInfo = $getID3->analyze($destinationPath . $filename)) {
$media->duree = $fileInfo['playtime_string'];
}
$media->save();
break;
}//end switch
2019-07-22 14:54:42 +02:00
2022-04-19 16:07:27 +02:00
$id = $media->id;
$media = Media::find($id);
2021-06-01 17:11:27 +02:00
// ---- Index dans Elasticsearch
$media = Media::where('id', $media->id)->first();
2021-06-01 17:11:27 +02:00
$media->addToIndex();
// ---- Historique des actions
2022-04-20 15:23:31 +02:00
$historique = new Historique();
2022-04-19 16:07:27 +02:00
if ($user = Auth::user()) {
2021-06-01 17:11:27 +02:00
$historique->user_id = $user->id;
}
$historique->media_id = $media->id;
2022-04-19 16:07:27 +02:00
if ($replaceMediaId == 0) {
$historique->type = "Création";
2021-06-01 17:11:27 +02:00
$historique->description = "Média ajouté";
2022-04-19 16:07:27 +02:00
} else {
$historique->type = "Modification";
2021-06-01 17:11:27 +02:00
$historique->description = "Le média a été remplacé";
}
$historique->save();
2019-05-29 14:05:54 +02:00
2022-04-19 16:07:27 +02:00
$filest = array();
$filest['name'] = $filename;
$filest['uid'] = $uid;
$filest['libelle'] = $media->libelle;
$filest['id'] = $media->id;
$filest['folder'] = $media->folder;
$filest['extension'] = $media->extension;
$filest['typemedia_id'] = $media->typemedia_id;
2022-04-19 16:07:27 +02:00
$filesa['files'][] = $filest;
}//end if
}//end foreach
return $filesa;
}//end if
2021-06-01 17:11:27 +02:00
}
public function storeMediaV2(Request $request)
{
2022-04-19 16:07:27 +02:00
$uid = $request->input('uid');
$sujet_id = $request->input('sujet_id');
$dossier_id = $request->input('dossier_id');
$replaceMediaId = $request->input('replaceMediaId');
2022-04-19 16:07:27 +02:00
if ($dossier_id == 0) {
$dossier_id = null;
2021-06-01 17:11:27 +02:00
}
2022-04-19 16:07:27 +02:00
$filesa = [];
$acceptFileTypes = array('gif','jpeg', 'jpg','png','mp4','mp3','psd','ai','svg','pdf');
2021-06-01 17:11:27 +02:00
if (!$uid) {
2022-04-20 15:23:31 +02:00
$uid = Str::uuid();
2021-06-01 17:11:27 +02:00
}
$file = $request->file('files');
if (!empty($file)) {
2022-04-19 16:07:27 +02:00
$extension = strtolower($file->getClientOriginalExtension());
$originalName = str_replace("." . $extension, "", $file->getClientOriginalName());
if (!in_array($extension, $acceptFileTypes)) {
return array("false");
2021-06-01 17:11:27 +02:00
}
2022-04-19 16:07:27 +02:00
if (!in_array($extension, $acceptFileTypes)) {
return array("error" => "Ce type de fichier n'est pas accepté.");
2021-06-01 17:11:27 +02:00
}
2022-04-20 15:23:31 +02:00
// * check the error status
if ($file->getError() != 0) {
Log::error('error ' . $file->getError() . ' in file ' . $request->resumableFilename);
}
2022-04-20 15:23:31 +02:00
$temp_dir = 'uploads';
/**
* init the destination file (format <filename.ext>.part<#chunk>
* the file is stored in a temporary directory
*/
2022-04-19 16:07:27 +02:00
if (isset($request->resumableIdentifier) && trim($request->resumableIdentifier) != '') {
2022-04-20 15:23:31 +02:00
$temp_dir .= "/{$request->resumableIdentifier}";
}
2022-04-20 15:23:31 +02:00
$dest_file = "{$temp_dir}/{$request->resumableFilename}.part{$request->resumableChunkNumber}";
2022-04-20 15:23:31 +02:00
// * create the temporary directory
if (!is_dir($temp_dir)) {
mkdir($temp_dir, 0777, true);
}
2022-04-20 15:23:31 +02:00
// * move the temporary file
if (!move_uploaded_file($file->getPathname(), $dest_file)) {
2022-04-20 15:23:31 +02:00
Log::error(
//phpcs:ignore Generic.Files.LineLength.TooLong
"Error saving (move_uploaded_file) chunk $request->resumableChunkNumber for file $request->resumableFilename"
);
} else {
2020-07-17 11:17:54 +02:00
$filename = $uid . '.' . $extension;
2022-04-20 15:23:31 +02:00
// * check if all the parts present, and create the final destination file
$isLast = $this->createFileFromChunks(
$temp_dir,
$request->resumableFilename,
$request->resumableChunkSize,
$request->resumableTotalSize,
$request->resumableTotalChunks,
$filename
);
2021-06-01 17:11:27 +02:00
if ($isLast) {
2022-04-19 16:07:27 +02:00
$destinationPath = $this->getMediaFolder() . "/";
2022-04-20 15:23:31 +02:00
// * si on upload un média pour remplacer un fichier par un autre
2022-04-19 16:07:27 +02:00
if ($replaceMediaId != 0) {
2022-04-20 15:23:31 +02:00
// * on récupère le média à modifier
/** @var \App\Models\Media $media */
$media = Media::where('id', $replaceMediaId)->firstOrFail();
2022-04-20 15:23:31 +02:00
// * On déplace le fichier dans le répertoire des médias
2022-04-19 16:07:27 +02:00
Storage::move("uploads/" . $filename, $destinationPath . $filename);
2022-04-20 15:23:31 +02:00
// * supprime les fichiers médias stockés sur disque
2022-04-19 16:07:27 +02:00
$filesfF = Storage::files($media->folder . "/");
$filepath = preg_quote($media->folder . $media->uid, '/');
$matchingFiles = preg_grep('/^' . $filepath . '/', $filesfF);
Storage::delete($matchingFiles);
$media->isDefault = 0;
$media->save();
2022-04-19 16:07:27 +02:00
} else {
2022-04-20 15:23:31 +02:00
// * On déplace le fichier dans le répertoire des médias
2022-04-19 16:07:27 +02:00
Storage::move("uploads/" . $filename, $destinationPath . $filename);
2022-04-20 15:23:31 +02:00
// * on créé un média en bdd
2022-04-19 16:07:27 +02:00
$media = new Media();
$media->dossier_id = $dossier_id;
2022-04-19 16:07:27 +02:00
$media->sujet_id = $sujet_id;
2022-04-20 15:23:31 +02:00
// * Par défaut FR
$media->langue_id = 1;
2022-04-20 15:23:31 +02:00
// * Par défaut propriété de la marque
$media->copyright_id = 3;
2022-04-19 16:07:27 +02:00
}//end if
$media->extension = $extension;
2022-04-19 16:07:27 +02:00
$media->folder = $destinationPath;
if ($replaceMediaId == 0) {
$media->libelle = mb_substr($originalName, 0, 50, "UTF-8");
$media->created_by = Auth::user()->id;
}
2022-04-19 16:07:27 +02:00
$media->uid = $uid;
$media->taille = $this->formatBytes($this->getFileSize($destinationPath . $filename));
switch ($extension) {
2022-04-20 15:23:31 +02:00
// * Photo (1)
2022-04-19 16:07:27 +02:00
case 'gif':
case 'jpeg':
case 'jpg':
case 'png':
case 'ai':
case 'pdf':
case 'psd':
$media->typemedia_id = 1;
$im = new \imagick($destinationPath . $filename);
if (in_array($extension, array("pdf", "ai", "psd", "gif"))) {
$im->setIteratorIndex(0);
}
2021-06-01 17:11:27 +02:00
2022-04-19 16:07:27 +02:00
$resolutions = $im->getImageResolution();
$media->resolution = round($resolutions['x'] * 2.54);
$imageprops = $im->getImageGeometry();
$media->largeur = $imageprops['width'];
$media->hauteur = $imageprops['height'];
if ($media->resolution != 0) {
$media->largeur_mm = ceil(($media->largeur * 2.54 / $media->resolution) * 10);
$media->hauteur_mm = ceil(($media->hauteur * 2.54 / $media->resolution) * 10);
} else {
$media->largeur_mm = "";
$media->hauteur_mm = "";
}
$media->save();
$im->destroy();
// ---- Creation des vignettes de base
$this->createSysThumb($media);
// ---- Creation des vignettes en lien avec le sujet du média
if (isset($sujet_id)) {
$this->createThumb($media);
}
break;
2022-04-20 15:23:31 +02:00
// * Illustration/Vectorielle (2)
2022-04-19 16:07:27 +02:00
case 'svg':
$media->typemedia_id = 2;
$media->save();
break;
2022-04-20 15:23:31 +02:00
// * Vidéo (3)
2022-04-19 16:07:27 +02:00
case 'mp4':
$media->typemedia_id = 3;
$getID3 = new \getID3();
if ($fileInfo = $getID3->analyze($destinationPath . $filename)) {
$media->largeur = $fileInfo['video']['resolution_x'];
$media->hauteur = $fileInfo['video']['resolution_y'];
$media->duree = $fileInfo['playtime_string'];
}
$media->save();
break;
2022-04-20 15:23:31 +02:00
// * Audio (4)
2022-04-19 16:07:27 +02:00
case 'mp3':
$media->typemedia_id = 4;
$getID3 = new \getID3();
if ($fileInfo = $getID3->analyze($destinationPath . $filename)) {
$media->duree = $fileInfo['playtime_string'];
}
$media->save();
break;
}//end switch
2022-04-19 16:07:27 +02:00
$id = $media->id;
$media = Media::find($id);
// ---- Index dans Elasticsearch
$media = Media::where('id', $media->id)->first();
$media->addToIndex();
// ---- Historique des actions
2022-04-20 15:23:31 +02:00
$historique = new Historique();
2022-04-19 16:07:27 +02:00
if ($user = Auth::user()) {
$historique->user_id = $user->id;
}
$historique->media_id = $media->id;
2022-04-19 16:07:27 +02:00
if ($replaceMediaId == 0) {
$historique->type = "Création";
$historique->description = "Média ajouté";
2022-04-19 16:07:27 +02:00
} else {
$historique->type = "Modification";
$historique->description = "Le média a été remplacé";
}
$historique->save();
return response()->json($media);
2022-04-19 16:07:27 +02:00
}//end if
}//end if
}//end if
}
/**
* Check if all the parts exist, and
* gather all the parts of the file together
2021-06-01 17:11:27 +02:00
*
2022-04-20 15:23:31 +02:00
* @param string $temp_dir The temporary directory holding all the parts of the file.
* @param string $fileName The original file name.
* @param integer $chunkSize Each chunk size (in bytes).
* @param integer $totalSize Original file size (in bytes).
* @param integer $total_files
* @param string $finalName
2022-04-19 16:07:27 +02:00
* @return boolean
*/
2022-04-20 15:23:31 +02:00
private function createFileFromChunks(
string $temp_dir,
string $fileName,
int $chunkSize,
int $totalSize,
int $total_files,
string $finalName
): bool {
// * count all the parts of this file
$total_files_on_server_size = 0;
2022-04-19 16:07:27 +02:00
$temp_total = 0;
foreach (scandir($temp_dir) as $file) {
$temp_total = $total_files_on_server_size;
$tempfilesize = filesize($temp_dir . '/' . $file);
$total_files_on_server_size = $temp_total + $tempfilesize;
}
2022-04-20 15:23:31 +02:00
// * check that all the parts are present
// * If the Size of all the chunks on the server is equal to the size of the file uploaded.
if ($total_files_on_server_size >= $totalSize) {
2022-04-20 15:23:31 +02:00
// * create the final destination file
if (($fp = fopen("uploads/{$finalName}", 'w')) !== false) {
2022-04-19 16:07:27 +02:00
for ($i = 1; $i <= $total_files; $i++) {
2022-04-20 15:23:31 +02:00
fwrite($fp, file_get_contents("{$temp_dir}/{$fileName}.part{$i}"));
}
fclose($fp);
} else {
Log::error('cannot create the destination file');
return false;
}
2022-04-20 15:23:31 +02:00
// * rename the temporary directory (to avoid access from other
// * concurrent chunks uploads) and than delete it
2022-04-19 16:07:27 +02:00
if (rename($temp_dir, $temp_dir . '_UNUSED')) {
$this->rrmdir($temp_dir . '_UNUSED');
} else {
$this->rrmdir($temp_dir);
}
return true;
2022-04-19 16:07:27 +02:00
}//end if
return false;
}
/**
* Delete a directory RECURSIVELY
2021-06-01 17:11:27 +02:00
*
2022-04-20 15:23:31 +02:00
* @param string $dir Directory path.
* @return void
2021-06-01 17:11:27 +02:00
* @link http://php.net/manual/en/function.rmdir.php
*/
2022-04-20 15:23:31 +02:00
private function rrmdir(string $dir): void
2021-06-01 17:11:27 +02:00
{
if (is_dir($dir)) {
$objects = scandir($dir);
foreach ($objects as $object) {
if ($object != "." && $object != "..") {
if (filetype($dir . "/" . $object) == "dir") {
$this->rrmdir($dir . "/" . $object);
} else {
unlink($dir . "/" . $object);
}
}
}
reset($objects);
rmdir($dir);
}
}
2019-05-29 14:05:54 +02:00
}