123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483 |
- <?php
- namespace Dcat\Admin\Form\Field;
- use Dcat\Admin\Admin;
- use Illuminate\Support\Arr;
- use Illuminate\Support\Facades\Storage;
- use Illuminate\Support\Facades\URL;
- use Illuminate\Support\Facades\Validator;
- use Symfony\Component\HttpFoundation\File\UploadedFile;
- use Symfony\Component\HttpFoundation\Response;
- trait UploadField
- {
- /**
- * Upload directory.
- *
- * @var string
- */
- protected $directory = '';
- /**
- * File name.
- *
- * @var null
- */
- protected $name = null;
- /**
- * Storage instance.
- *
- * @var \Illuminate\Filesystem\Filesystem
- */
- protected $storage;
- /**
- * If use unique name to store upload file.
- *
- * @var bool
- */
- protected $useUniqueName = false;
- /**
- * If use sequence name to store upload file.
- *
- * @var bool
- */
- protected $useSequenceName = false;
- /**
- * Controls the storage permission. Could be 'private' or 'public'.
- *
- * @var string
- */
- protected $storagePermission;
- /**
- * @var string
- */
- protected $tempFilePath;
- /**
- * Retain file when delete record from DB.
- *
- * @var bool
- */
- protected $retainable = false;
- /**
- * Initialize the storage instance.
- *
- * @return void.
- */
- protected function initStorage()
- {
- $this->disk(config('admin.upload.disk'));
- if (! $this->storage) {
- $this->storage = false;
- }
- }
- /**
- * If name already exists, rename it.
- *
- * @param $file
- *
- * @return void
- */
- public function renameIfExists(UploadedFile $file)
- {
- if ($this->getStorage()->exists("{$this->getDirectory()}/$this->name")) {
- $this->name = $this->generateUniqueName($file);
- }
- }
- /**
- * @return string
- */
- protected function getUploadPath()
- {
- return "{$this->getDirectory()}/$this->name";
- }
- /**
- * Get store name of upload file.
- *
- * @param UploadedFile $file
- *
- * @return string
- */
- protected function getStoreName(UploadedFile $file)
- {
- if ($this->useUniqueName) {
- return $this->generateUniqueName($file);
- }
- if ($this->useSequenceName) {
- return $this->generateSequenceName($file);
- }
- if ($this->name instanceof \Closure) {
- return $this->name->call($this, $file);
- }
- if (is_string($this->name)) {
- return $this->name;
- }
- return $file->getClientOriginalName();
- }
- /**
- * Get directory for store file.
- *
- * @return mixed|string
- */
- public function getDirectory()
- {
- if ($this->directory instanceof \Closure) {
- return call_user_func($this->directory, $this->form);
- }
- return $this->directory ?: $this->defaultDirectory();
- }
- /**
- * Indicates if the underlying field is retainable.
- *
- * @return $this
- */
- public function retainable($retainable = true)
- {
- $this->retainable = $retainable;
- return $this;
- }
- /**
- * Upload File.
- *
- * @param UploadedFile $file
- *
- * @return Response
- */
- public function upload(UploadedFile $file)
- {
- try {
- $request = request();
- $id = $request->get('_id');
- /* @var \Dcat\Admin\Support\WebUploader $webUploader */
- $webUploader = Admin::context()->webUploader;
- if (! $id) {
- return $webUploader->responseErrorMessage(403, 'Missing id');
- }
- if ($errors = $this->getErrorMessages($file)) {
- $webUploader->deleteTempFile();
- return $webUploader->responseValidationMessage($errors);
- }
- $this->name = $this->getStoreName($file);
- $this->renameIfExists($file);
- $this->prepareFile($file);
- if (! is_null($this->storagePermission)) {
- $result = $this->getStorage()->putFileAs($this->getDirectory(), $file, $this->name, $this->storagePermission);
- } else {
- $result = $this->getStorage()->putFileAs($this->getDirectory(), $file, $this->name);
- }
- $webUploader->deleteTempFile();
- if ($result) {
- $path = $this->getUploadPath();
- return $webUploader->responseUploaded($path, $this->objectUrl($path));
- }
- return $webUploader->responseFailedMessage();
- } catch (\Throwable $e) {
- $webUploader->deleteTempFile();
- throw $e;
- }
- }
- /**
- * @param UploadedFile $file
- */
- protected function prepareFile(UploadedFile $file)
- {
- }
- /**
- * Specify the directory and name for upload file.
- *
- * @param string $directory
- * @param null|string $name
- *
- * @return $this
- */
- public function move($directory, $name = null)
- {
- $this->dir($directory);
- $this->name($name);
- return $this;
- }
- /**
- * Specify the directory upload file.
- *
- * @param string $dir
- *
- * @return $this
- */
- public function dir($dir)
- {
- if ($dir) {
- $this->directory = $dir;
- }
- return $this;
- }
- /**
- * Set name of store name.
- *
- * @param string|callable $name
- *
- * @return $this
- */
- public function name($name)
- {
- if ($name) {
- $this->name = $name;
- }
- return $this;
- }
- /**
- * Use unique name for store upload file.
- *
- * @return $this
- */
- public function uniqueName()
- {
- $this->useUniqueName = true;
- return $this;
- }
- /**
- * Use sequence name for store upload file.
- *
- * @return $this
- */
- public function sequenceName()
- {
- $this->useSequenceName = true;
- return $this;
- }
- /**
- * Generate a unique name for uploaded file.
- *
- * @param UploadedFile $file
- *
- * @return string
- */
- protected function generateUniqueName(UploadedFile $file)
- {
- return md5(uniqid()).'.'.$file->getClientOriginalExtension();
- }
- /**
- * Generate a sequence name for uploaded file.
- *
- * @param UploadedFile $file
- *
- * @return string
- */
- protected function generateSequenceName(UploadedFile $file)
- {
- $index = 1;
- $extension = $file->getClientOriginalExtension();
- $originalName = $file->getClientOriginalName();
- $newName = $originalName.'_'.$index.'.'.$extension;
- while ($this->getStorage()->exists("{$this->getDirectory()}/$newName")) {
- $index++;
- $newName = $originalName.'_'.$index.'.'.$extension;
- }
- return $newName;
- }
- /**
- * @param UploadedFile $file
- *
- * @return bool|\Illuminate\Support\MessageBag
- */
- protected function getErrorMessages(UploadedFile $file)
- {
- $rules = $attributes = [];
- if (! $fieldRules = $this->getRules()) {
- return false;
- }
- $rules[$this->column] = $fieldRules;
- $attributes[$this->column] = $this->label;
- /* @var \Illuminate\Validation\Validator $validator */
- $validator = Validator::make([$this->column => $file], $rules, $this->validationMessages, $attributes);
- if (! $validator->passes()) {
- $errors = $validator->errors()->getMessages()[$this->column];
- return implode('; ', $errors);
- }
- }
- /**
- * Destroy original files.
- *
- * @return void.
- */
- public function destroy()
- {
- if ($this->retainable) {
- return;
- }
- $this->deleteFile($this->original);
- }
- /**
- * Destroy original files.
- *
- * @param $file
- */
- public function destroyIfChanged($file)
- {
- if (! $file || ! $this->original) {
- return $this->destroy();
- }
- $file = array_filter((array) $file);
- $original = (array) $this->original;
- $this->deleteFile(Arr::except(array_combine($original, $original), $file));
- }
- /**
- * Destroy files.
- *
- * @param string|array $path
- */
- public function deleteFile($paths)
- {
- if (! $paths) {
- return;
- }
- $storage = $this->getStorage();
- foreach ((array) $paths as $path) {
- if ($storage->exists($path)) {
- $storage->delete($path);
- } else {
- $prefix = $storage->url('');
- $path = str_replace($prefix, '', $path);
- if ($storage->exists($path)) {
- $storage->delete($path);
- }
- }
- }
- }
- /**
- * Get storage instance.
- *
- * @return \Illuminate\Filesystem\Filesystem|null
- */
- public function getStorage()
- {
- if ($this->storage === null) {
- $this->initStorage();
- }
- return $this->storage;
- }
- /**
- * Set disk for storage.
- *
- * @param string $disk Disks defined in `config/filesystems.php`.
- *
- * @throws \Exception
- *
- * @return $this
- */
- public function disk($disk)
- {
- try {
- $this->storage = Storage::disk($disk);
- } catch (\Exception $exception) {
- if (! array_key_exists($disk, config('filesystems.disks'))) {
- admin_error(
- 'Config error.',
- "Disk [$disk] not configured, please add a disk config in `config/filesystems.php`."
- );
- return $this;
- }
- throw $exception;
- }
- return $this;
- }
- /**
- * Get file visit url.
- *
- * @param string $path
- *
- * @return string
- */
- public function objectUrl($path)
- {
- if (URL::isValidUrl($path)) {
- return $path;
- }
- return $this->getStorage()->url($path);
- }
- /**
- * @param $permission
- *
- * @return $this
- */
- public function storagePermission($permission)
- {
- $this->storagePermission = $permission;
- return $this;
- }
- }
|