UploadService.php 7.1 KB
<?php

namespace App\Services;


use App\Helper\FileEtag;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;
use Illuminate\Http\UploadedFile;

/**
 * Class UploadServer
 * @package App\Services
 */
class UploadService extends BaseService
{

    /**
     * 默认配置
     * @see $defaultConfig
     * @var array
     */
    public $config = [];

    /**
     *  默认配置
     * @var array
     */
    public $defaultConfig = [
        // 上传文件的大小范围
        'size' => [
            'max' => 1024 * 1024 * 2,    // 2M
        ],
        // 磁盘
        'disk'  =>  'upload',
        // 扩展名
        'ext' => [
            'png', 'jpg', 'jpeg', 'gif'
        ],
        // 目录
        'path' => '',
    ];

    /**
     * @param string|array $config
     * @author:dc
     * @time 2022/1/7 14:38
     */
    private function config($config = 'default')
    {
        if (is_array($config)) {
            $driver = $config['driver'];
        } else {
            $driver = $config;
        }

        // 加载配置
        $this->config = $this->defaultConfig;
        if ($driver != 'default') {
            $conf = config('upload.' . $driver);
            if ($conf) {
                // 合并默认配置
                $this->config = array_merge($this->config, $conf);
            }
        }

        // 追加目录
        if ($config['path'] ?? '') {
            $this->config['path'] = $this->config['path'] . (strpos($config['path'], '/') !== 0 ? '/' : '') . $config['path'];
        }
    }

    /**
     *
     * @param string $input_file
     * @param string $config
     * @return string
     * @throws \Exception
     * @author:dc
     * @time 2021/12/30 16:37
     */
    public function put($input_file = "file", $config = 'default'): string
    {
        $this->config($config);

        if ($input_file instanceof UploadedFile) {
            $file =   &$input_file;
        } else {
            // 是否是已存在服务器的图片
            if (Str::contains($input_file, env('APP_URL'))) {
                return $input_file;
            } else {
                // 获取post上传文件
                $file = request()->file($input_file);
                // 如果不是上传,是否本地文件
                if (!$file && is_file($input_file)) {
                    // 获取文件的名字
                    $origin_name = explode(DIRECTORY_SEPARATOR, $input_file);
                    !is_array($origin_name) && $origin_name = [$origin_name];
                    // 创建一个上传对象
                    $file = UploadedFile::createFromBase(new \Symfony\Component\HttpFoundation\File\UploadedFile($input_file, array_pop($origin_name)));
                }
            }

        }

        if ($file) {
            // 验证扩展名
            if (!in_array($file->extension(), $this->config['ext'])) {
                $this->fail('文件扩展名不匹配,文件扩展名支持' . implode(',', $this->config['ext']));
            }

            // 验证文件大小
            if ($file->getSize() > $this->config['size']['max']) {
                $this->fail('文件大小超出' . ($this->config['size']['max'] / 1024 / 1024) . 'M');
            }

            //判断文件hash是否已存在
            if ($filename = $this->getFileHash($file)) {
                return $filename;
            }

            $pathDate = date('Y-m');

            // 保存处理过的图片
            if (!empty($img)) {
                // 保存的图片名称
                $save_name = $this->config['path'] . '/' . $pathDate . '/' . $file->hashName();
                // 保存文件
                if (!Storage::disk($this->config['disk'])
                    ->put($save_name, $img->getEncoded())) {
                    $save_name = '';
                }
            } else {
                // 保存文件
                $save_name = $file->storeAs($this->config['path'] . '/' . $pathDate, $file->hashName(), $this->config['disk']);
            }

            if ($save_name) {
                //保存文件hash
                $this->setFileHash($file, $save_name);
                // 返回地址
                return $save_name;
            }

            $this->fail( '上传失败');

        }
        // 异常
        $this->fail('请上传文件');
    }

    /**
     * 批量上传
     * @param string $input_file
     * @param string $config
     * @return array
     * @throws \Exception
     * @author:dc
     * @time 2021/12/30 16:36
     */
    public function puts($input_file = "file", $config = 'default'): array
    {
        $request = request();
        $files = $request->post($input_file, []);
        $files_ = $request->file($input_file);
        if ($files_) {
            $files = array_merge($files, $files_);
        }
        $filename = [];
        if ($files instanceof UploadedFile) {
            $filename[] = $this->put($files, $config);
        } else if ($files) {
            foreach ($files as $file) {
                $filename[] = $this->put($file, $config);
            }
        } else {
            // 异常
            $this->fail('请上传文件');
        }

        return $filename;
    }

    /**
     * 上传文件,文件内容
     * @param string $filename
     * @param string $content
     * @param string $config
     * @return string
     * @throws \App\Exceptions\BsideGlobalException
     * @author:dc
     * @time 2022/1/7 14:45
     */
    public function filePut(string $filename, string $content, $config = 'default')
    {
        if ($content) {
            $this->config($config);
            $save_name = $this->config['path'] . '/' . $filename;
            // 保存文件
            $result = Storage::disk($this->config['disk'])->put($save_name, $content);

            if ($result) {
                // 返回地址
                return $save_name;
            }

            $this->fail('上传失败');

        }
        // 异常
        $this->fail('请上传文件');
    }

    /**
     * 文件hash是否存在 存在返回文件路径
     * @param $file
     * @return mixed|string|null
     */
    protected function getFileHash($file)
    {
        $hash = FileEtag::sum($file)[0];
        if (!$hash) {
            return '';
        }
        return DB::table('gl_file_hash')->where('hash', $hash)->value('filename');
    }

    /**
     * 保存文件hash
     * @param $file
     * @param $save_path
     * @return bool
     */
    protected function setFileHash($file, $save_path): bool
    {
        $hash = FileEtag::sum($file)[0];

        if (!$hash) {
            return false;
        }
        $data = [
            'filename' => $save_path,
            'hash' => $hash,
        ];
        DB::table('gl_file_hash')->insert($data);
        return true;
    }

    /**
     * 文件地址转本地路径
     * @param $url
     * @param string $disk
     * @return array|string|string[]
     * @author zbj
     * @date 2023/4/20
     */
    public function url2path($url, $disk = 'upload'){
        $upload_url = config('filesystems')['disks'][$disk]['url'];
        return str_replace($upload_url . '/', '', $url);
    }
}