|
|
@@ -18,16 +18,81 @@ class FileService
|
|
|
*/
|
|
|
public function saveUploadedFile($path, $file): File
|
|
|
{
|
|
|
- Storage::disk('public')->put($path . '/' .$file->getClientOriginalName(), $file->getContent());
|
|
|
- return File::query()->updateOrCreate([
|
|
|
- 'link' => url('/storage/') . '/' . $path . '/' .$file->getClientOriginalName(),
|
|
|
- 'path' => $path . '/' .$file->getClientOriginalName(),
|
|
|
+ $originalName = $this->sanitizeOriginalName((string)$file->getClientOriginalName());
|
|
|
+ $storedFilename = $this->buildStoredFilename($originalName);
|
|
|
+ $relativePath = $this->buildUniquePath($path, $storedFilename);
|
|
|
+
|
|
|
+ Storage::disk('public')->put($relativePath, $file->getContent());
|
|
|
+
|
|
|
+ return File::query()->create([
|
|
|
+ 'link' => url('/storage/' . $relativePath),
|
|
|
+ 'path' => $relativePath,
|
|
|
'user_id' => auth()->user()->id,
|
|
|
- 'original_name' => $file->getClientOriginalName(),
|
|
|
+ 'original_name' => $originalName,
|
|
|
'mime_type' => $file->getClientMimeType(),
|
|
|
]);
|
|
|
}
|
|
|
|
|
|
+ private function sanitizeOriginalName(string $originalName): string
|
|
|
+ {
|
|
|
+ $name = basename(str_replace('\\', '/', $originalName));
|
|
|
+ $name = preg_replace('/[\x00-\x1F\x7F]+/u', '', $name) ?? '';
|
|
|
+ $name = trim($name);
|
|
|
+
|
|
|
+ return $name === '' ? 'file' : $name;
|
|
|
+ }
|
|
|
+
|
|
|
+ private function buildStoredFilename(string $originalName): string
|
|
|
+ {
|
|
|
+ $baseName = pathinfo($originalName, PATHINFO_FILENAME);
|
|
|
+ $extension = pathinfo($originalName, PATHINFO_EXTENSION);
|
|
|
+
|
|
|
+ $baseName = preg_replace('/[<>:|?*\/\\\\]+/u', '_', $baseName) ?? '';
|
|
|
+ $baseName = preg_replace('/\s+/u', ' ', $baseName) ?? '';
|
|
|
+ $baseName = trim($baseName, " .\t\n\r\0\x0B");
|
|
|
+
|
|
|
+ if ($baseName === '' || $baseName === '.' || $baseName === '..') {
|
|
|
+ $baseName = 'file';
|
|
|
+ }
|
|
|
+
|
|
|
+ if (function_exists('mb_substr')) {
|
|
|
+ $baseName = mb_substr($baseName, 0, 150);
|
|
|
+ } else {
|
|
|
+ $baseName = substr($baseName, 0, 150);
|
|
|
+ }
|
|
|
+
|
|
|
+ $extension = preg_replace('/[^A-Za-z0-9]+/', '', $extension) ?? '';
|
|
|
+
|
|
|
+ return $extension === '' ? $baseName : $baseName . '.' . $extension;
|
|
|
+ }
|
|
|
+
|
|
|
+ private function buildUniquePath(string $directory, string $filename): string
|
|
|
+ {
|
|
|
+ $directory = trim($directory, '/');
|
|
|
+ $basePath = $directory === '' ? $filename : $directory . '/' . $filename;
|
|
|
+
|
|
|
+ if (!Storage::disk('public')->exists($basePath)) {
|
|
|
+ return $basePath;
|
|
|
+ }
|
|
|
+
|
|
|
+ $baseName = pathinfo($filename, PATHINFO_FILENAME);
|
|
|
+ $extension = pathinfo($filename, PATHINFO_EXTENSION);
|
|
|
+
|
|
|
+ for ($index = 1; $index < 10000; $index++) {
|
|
|
+ $candidateName = $baseName . ' (' . $index . ')';
|
|
|
+ if ($extension !== '') {
|
|
|
+ $candidateName .= '.' . $extension;
|
|
|
+ }
|
|
|
+
|
|
|
+ $candidatePath = $directory === '' ? $candidateName : $directory . '/' . $candidateName;
|
|
|
+ if (!Storage::disk('public')->exists($candidatePath)) {
|
|
|
+ return $candidatePath;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return $basePath;
|
|
|
+ }
|
|
|
+
|
|
|
|
|
|
/**
|
|
|
* @param string $path
|
|
|
@@ -76,4 +141,4 @@ class FileService
|
|
|
}
|
|
|
|
|
|
|
|
|
-}
|
|
|
+}
|