Skip to content

Commit

Permalink
resolve mimetype & uploader mimetype
Browse files Browse the repository at this point in the history
  • Loading branch information
ArrayIterator committed Oct 18, 2023
1 parent e641e70 commit de6a8d5
Show file tree
Hide file tree
Showing 2 changed files with 161 additions and 100 deletions.
1 change: 1 addition & 0 deletions Traits/MediaPathTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,7 @@ public function determinePathMimeType(
'text/javascript',
'text/ecmascript',
'application/sql',
'application/x-sql',
'text/x-php',
'application/x-php',
'application/json',
Expand Down
260 changes: 160 additions & 100 deletions Uploader/Abstracts/AbstractUploader.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,21 @@
use Psr\Http\Message\UploadedFileInterface;
use Throwable;
use function file_exists;
use function file_get_contents;
use function file_put_contents;
use function filesize;
use function function_exists;
use function is_file;
use function is_string;
use function mime_content_type;
use function pathinfo;
use function preg_match;
use function reset;
use function sprintf;
use function unlink;
use const PATHINFO_EXTENSION;
use const PATHINFO_FILENAME;
use const PHP_INT_MAX;

class AbstractUploader
{
Expand Down Expand Up @@ -161,130 +168,183 @@ public function uploadAttachment(
$uploadedFile = MimeType::resolveMediaTypeUploadedFiles($uploadedFile);
$originalFileName = $uploadedFile->getClientFilename();
$progress = $this->media->upload($uploadedFile, $request);
if (!$progress->isDone()) {
return new UploadedFileMetadata(
$this,
$type,
$request,
$uploadedFile,
$progress,
false
$mimeFile = $progress->targetCacheFile
. '.mime_type.'
. $progress->handler->processor->chunk->partialExtension;
$newMimeType = null;
if ($progress->handler->processor->isNewRequestId) {
$newMimeType = $uploadedFile->getClientMediaType();
if (!file_exists($mimeFile)) {
// save mime-type
file_put_contents($mimeFile, $newMimeType);
}
$this->getMedia()->getManager()->attach(
'jsonResponder.format',
function ($e) use ($newMimeType) {
$e['mime'] = $newMimeType;
return $e;
},
priority: PHP_INT_MAX - 5
);
} elseif (is_file($mimeFile)) {
$validMime = false;
// check filesize
if (filesize($mimeFile) <= 128) {
$mime = Consolidation::callbackReduceError(fn() => file_get_contents($mimeFile));
if (is_string($mime)
&& strlen($mime) <= 128
&& preg_match('~^[^/]+/\S+$~', $mime)
&& MimeType::fromMimeType($mime)
) {
$newMimeType = $mime;
$validMime = true;
}
}
if (!$validMime) {
// delete if longer
Consolidation::callbackReduceError(fn() => unlink($mimeFile));
}
}

$extension = pathinfo($uploadedFile->getClientFilename(), PATHINFO_EXTENSION);
$newMimeType = MimeType::mime($extension);
if ($progress->getSize() > $uploadedFile->getSize()
&& $newMimeType !== $uploadedFile->getClientMediaType()
// check the mime type
&& (
function_exists('mime_content_type')
&& ($newMime = mime_content_type($progress->targetCacheFile))
&& $newMime !== $uploadedFile->getClientMediaType()
|| ! ($newMime??null)
)
) {
$newMime ??= $newMimeType;
if ($newMimeType && $newMimeType !== $uploadedFile->getClientMediaType()) {
$uploadedFile = new UploadedFile(
$uploadedFile->getStream(),
$uploadedFile->getSize(),
$uploadedFile->getError(),
$uploadedFile->getClientFilename(),
$newMime
$newMimeType
);
}

if ($type === self::TYPE_AVATAR) {
$filePath = $this->media->getAvatarUploadFullPathByUser($uploadedFile, $user, true);
$uploadedFile = $this->getUploadedFileAvatar(
if (!$progress->isDone()) {
return new UploadedFileMetadata(
$this,
$type,
$request,
$uploadedFile,
$filePath
$progress,
false
);
} else {
$uploadDirectory = match ($type) {
self::TYPE_UPLOAD => $this->media->determineUploadDirectory($uploadedFile, $user, true),
default => $this->media->determineDataDirectory($uploadedFile, $user, true),
};
$clientFileName = $this->media->filterFileNameUseLower($uploadedFile, true);
$filePath = $uploadDirectory . '/' . $clientFileName;
}

$fullPath = $progress->put(
$filePath,
$type === self::TYPE_AVATAR
);
try {
$extension = pathinfo($uploadedFile->getClientFilename(), PATHINFO_EXTENSION);
if (!$newMimeType) {
$newMimeType = MimeType::mime($extension);
if ($progress->getSize() > $uploadedFile->getSize()
&& $newMimeType !== $uploadedFile->getClientMediaType()
// check the mime type
&& (
function_exists('mime_content_type')
&& ($newMime = mime_content_type($progress->targetCacheFile))
&& $newMime !== $uploadedFile->getClientMediaType()
|| !($newMime ?? null)
)
) {
$newMime ??= $newMimeType;
$uploadedFile = new UploadedFile(
$uploadedFile->getStream(),
$uploadedFile->getSize(),
$uploadedFile->getError(),
$uploadedFile->getClientFilename(),
$newMime
);
}
}

if (!$fullPath) {
$progress->deletePartial();
throw new RuntimeException(
$this->translateContext(
'Could not save uploaded file',
'module',
'media-module'
)
);
}
if ($type === self::TYPE_AVATAR) {
$filePath = $this->media->getAvatarUploadFullPathByUser($uploadedFile, $user, true);
$uploadedFile = $this->getUploadedFileAvatar(
$uploadedFile,
$filePath
);
} else {
$uploadDirectory = match ($type) {
self::TYPE_UPLOAD => $this->media->determineUploadDirectory($uploadedFile, $user, true),
default => $this->media->determineDataDirectory($uploadedFile, $user, true),
};
$clientFileName = $this->media->filterFileNameUseLower($uploadedFile, true);
$filePath = $uploadDirectory . '/' . $clientFileName;
}

$basePath = $this->media->getAttachmentFileToBasePath($fullPath);
if (!$basePath) {
Consolidation::callbackReduceError(fn () => unlink($fullPath));
throw new RuntimeException(
$this->translateContext(
'Could not save uploaded file & determine target file.',
'module',
'media-module'
)
$fullPath = $progress->put(
$filePath,
$type === self::TYPE_AVATAR
);
}

try {
$attachment = $repository
->findOneBy([
'path' => $basePath,
'storage_type' => $type
]);
if (!$attachment) {
$name = pathinfo($originalFileName, PATHINFO_FILENAME);
$attachment = new $className();
$attachment->setEntityManager($em);
$attachment->setPath($basePath);
$attachment->setName($name?:$originalFileName);
$attachment->setStatus($attachment::PUBLISHED);
if (!$fullPath) {
$progress->deletePartial();
throw new RuntimeException(
$this->translateContext(
'Could not save uploaded file',
'module',
'media-module'
)
);
}

if ($user instanceof Admin || $user instanceof User) {
$attachment->setUser($user);
$attachment->setUserId($user->getId());
$basePath = $this->media->getAttachmentFileToBasePath($fullPath);
if (!$basePath) {
Consolidation::callbackReduceError(fn() => unlink($fullPath));
throw new RuntimeException(
$this->translateContext(
'Could not save uploaded file & determine target file.',
'module',
'media-module'
)
);
}

$attachment->setFileName($originalFileName);
$attachment->setStorageType($attachment::TYPE_UPLOAD);
$attachment->setSize($progress->getSize());
$attachment->setDeletedAt(null);
$attachment->setMimeType($uploadedFile->getClientMediaType());
$em->persist($attachment);
$em->flush();
} catch (Throwable $e) {
if (file_exists($fullPath)) {
Consolidation::callbackReduceError(fn() => unlink($fullPath));
try {
$attachment = $repository
->findOneBy([
'path' => $basePath,
'storage_type' => $type
]);
if (!$attachment) {
$name = pathinfo($originalFileName, PATHINFO_FILENAME);
$attachment = new $className();
$attachment->setEntityManager($em);
$attachment->setPath($basePath);
$attachment->setName($name ?: $originalFileName);
$attachment->setStatus($attachment::PUBLISHED);
}

if ($user instanceof Admin || $user instanceof User) {
$attachment->setUser($user);
$attachment->setUserId($user->getId());
}

$attachment->setFileName($originalFileName);
$attachment->setStorageType($attachment::TYPE_UPLOAD);
$attachment->setSize($progress->getSize());
$attachment->setDeletedAt(null);
$attachment->setMimeType($uploadedFile->getClientMediaType());
$em->persist($attachment);
$em->flush();
} catch (Throwable $e) {
if (file_exists($fullPath)) {
Consolidation::callbackReduceError(fn() => unlink($fullPath));
}
throw $e;
}
throw $e;
}

$result = new UploadedFileMetadata(
$this,
$type,
$request,
$uploadedFile,
$progress,
true,
$fullPath,
$attachment
);
if ($type === self::TYPE_AVATAR) {
$result = $this->dispatchAvatarUpload($result);
$result = new UploadedFileMetadata(
$this,
$type,
$request,
$uploadedFile,
$progress,
true,
$fullPath,
$attachment
);
if ($type === self::TYPE_AVATAR) {
$result = $this->dispatchAvatarUpload($result);
}
} finally {
if (is_file($mimeFile)) {
Consolidation::callbackReduceError(fn() => unlink($mimeFile));
}
}

return $result;
}

Expand Down

0 comments on commit de6a8d5

Please sign in to comment.