Laravel上传Excel文件的问题

1,975 阅读1分钟

1、普通代码

    //...
    $file = $request->file('file');
    $path = $file->store('public/checks');
    //...

2、错误信息

  • 1、上传的Excel文件有时候自动打包成了rar文件
  • 2、上传的Excel文件有时候自动报错了
"fopen(..\storage\app\public/checks/vEr8BInHAHwIbxnHUvmEkGlBsaF2z7V8kMfl2Xkd.): failed to open stream: Permission denied"

3、解决方案一

/**
 * 文件上传
 * @param \Illuminate\Http\Request $request
 * @return \Illuminate\Http\JsonResponse
 */
public function upload(Request $request)
{
    //设置文件后缀白名单
    $allowExt   = ["csv", "xls", "xlsx"];
    //设置存储目录
    $tmpPath    = 'storage/jschecks/' . date('Ym');
    $dirPath    = public_path($tmpPath);
    //如果目标目录不能创建
    if (!is_dir($dirPath) && !mkdir($dirPath, 0777,true)) {
        return $this->fail(401, '上传目录没有创建文件夹权限');
    }
    //如果目标目录没有写入权限
    if(is_dir($dirPath) && !is_writable($dirPath)) {
        return $this->fail(401, '上传目录没有写入权限');
    }
    //获取文件
    $file = $request->file('file');
    //校验文件
    if(isset($file) && $file->isValid()){
        $ext = $file->getClientOriginalExtension(); //上传文件的后缀
        //判断是否是Excel
        if(empty($ext) or in_array(strtolower($ext),$allowExt) === false){
            return $this->fail(400, '不允许的文件类型');
        }
        //生成文件名
        $fileName = uniqid() . '_' . dechex(microtime(true)) .'.'.$ext;
        try{
            //存储文件
            $path = $file->move($tmpPath, $fileName);
            $webPath = '/' . $path->getPath() . '/' . $fileName;

            $data['oldname']    = $file->getClientOriginalName();
            $data['newname']    = $fileName;
            $data['url']        = url($webPath);

            return $this->success_without_index('文件导入成功!', $data);
        }catch (Exception $ex){
            return $this->fail($ex->getCode(), $ex->getMessage());
        }

    }

    return $this->fail(400, '文件校验失败');
}

4、解决方案二

配合使用 Laravel Medialibrary

/**
 * 文件上传
 * @param Request $request
 * @return \Illuminate\Http\JsonResponse
 * @throws \Exception
 * @throws \Throwable
 */
public function upload(Request $request)
{
    //设置php页面最大执行时间:默认30s
    ini_set('max_execution_time', 300);
    //返回信息
    $data = [];
    //设置文件后缀白名单
    $allowExt   = ["csv", "xls", "xlsx"];
    //获取文件
    $file = $request->file('file');
    //简单验证必须有文件上传上来
    $validator = Validator::make($request->all(), [
        'file' => 'required'
    ]);
    //验证文件后缀
    $validator->after(function($validator) use ($file, $allowExt) {
        if (!in_array($file->guessClientExtension(), $allowExt)) {
            return $this->fail(400, '不允许的文件类型:请上传Excel文件!');
        }
    });
    if ($validator->fails()) {
        return $this->fail(400, '未发现有效文件:请上传Excel文件!');
    }
    $upload = '';
    DB::transaction(function () use ($file, &$data, &$upload) {
        //存储文件信息到数据库
        $upload = Upload::create([
            'file_name' => $file->getClientOriginalName(),
            'file_ext'  => $file->getClientOriginalExtension(),
            'category'  => 'check',
        ]);
        //存储到Laravel-Medialibrary
        $media  = $upload->addMediaFromRequest('file')
            ->toMediaCollection('uploads');
        $tmp['filename']    = $media->file_name;
        $tmp['url']         = $media->getFullUrl();
        $data               = $tmp;
    });

    //数据导入
    $process = new Process('php '. dirname(app_path()) .'/artisan tqsq2005:excel-import ' . $upload->uuid);
    //运行时间限制:默认60s
    $process->setTimeout(3600);
    //空闲时间限制
    //$process->setIdleTimeout(30);
    $process->run();
    //返回插入的数据数
    $upload             = $upload->fresh();
    $data['inserts']    = $upload->import_records;

    if (is_array($data) && $data['inserts'])
        return $this->success_without_index('成功导入'.$data['inserts'].'条数据!', $data);
    return $this->fail(400, '文件导入失败');
}