安装扩展和使用细节参考官方文档即可,这里更多的是介绍一些遇到的问题:
https://hyperf.wiki/2.0/#/zh-cn/filesystem
安装:
首先执行
composer require hyperf/filesystem
使用阿里云 OSS 适配器时执行
composer require xxtime/flysystem-aliyun-oss
发布配置文件:
php bin/hyperf.php vendor:publish hyperf/filesystem
其次是验证文件上传的问题:
以前 laravel 的写法是直接在 controller里
类似:
public function uploadFile(Request $request){
$rtn = RspHelper::makeJsonResponse();
$validator = Validator::make($request->all(), [
'type' => 'nullable|string',
'file' => 'required|file', // 注意这里
]);
if ($validator->fails()) {
RspHelper::setErr($rtn, 'PARAM_ERROR');
return response()->json($rtn);
};
$type = $request->input('type','attachment');
$file = $request->file('file');
}
但是在 hyperf 里, $request->all() 并没有文件,只能获取到 get 和 post的值:
定义文件:vendor/hyperf/http-server/src/Request.php
你也可以继续追函数, 找到文件(vendor/hyperf/http-message/src/Server/Request.php 这里面定义了请求来以后 get post file cookie 等是如何赋值给 request的)
而在 laravel 里 $request->all() 是有添加 file的:
定义文件在: vendor/laravel/framework/src/Illuminate/Http/Concerns/InteractsWithInput.php
i
n
p
u
t
=
a
r
r
a
y
r
e
p
l
a
c
e
r
e
c
u
r
s
i
v
e
(
input = array_replace_recursive(
input=arrayreplacerecursive(this->input(), $this->allFiles());
于是我第一反应是 hyperf 有bug 然后做了修改并提了 PR 见:https://github.com/hyperf/hyperf/pull/2529
但是后来发现 在hyperf 的 FomRequest.php 中的函数: ValidationData 有主动处理过这个问题:
protected function validationData(): array
{
return array_merge_recursive($this->all(), $this->getUploadedFiles());
}
而且还有 PR: https://github.com/hyperf-cloud/hyperf/pull/694
所以也就有了 我提的PR的对话。
那么针对这种情况上传文件的程序举例:
// 当然可以使用 merge ,但是我这里采用 自定义请求类的方式举例:
首先创建 请求类: php bin/hyperf.php gen:request UploadRequest
内容为:
<?php
declare(strict_types=1);
namespace App\Request;
use App\Constants\StatusCode;
use App\Exception\ApiException;
use Hyperf\Contract\ValidatorInterface;
use Hyperf\Validation\Request\FormRequest;
use Hyperf\Validation\ValidationException;
class UploadRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*/
public function authorize(): bool
{
return true;
}
/**
* Get the validation rules that apply to the request.
*/
public function rules(): array
{
return [
'type' => 'nullable|string',
'file' => 'required|file',
];
}
public function messages(): array
{
return [
'required' => ':attribute 必填',
'file' => ':attribute 必须上传',
];
}
// 这里我是希望走到我自己定义的 异常处理,你如果没有自定义,去掉这个函数的重写即可。
protected function failedValidation(ValidatorInterface $validator)
{
throw new ApiException(StatusCode::PARAM_ERROR, $validator->errors()->first());
}
}
controller里使用:
use App\Request\UploadRequest;
public function upload(UploadRequest $request, ResponseInterface $response, Filesystem $filesystem)
{
$type = $request->input('type','image');
$file = $request->file('file');
// $uploadData = $request->validated(); // 也可以使用这种方式获取参数
if(!$file->isValid()){
return '上传文件错误';
}
// XXXX 其他逻辑
}
OSS 的坑:
解决OSS 提示:
Notice: iconv(): Wrong charset, conversion from GBK' to
UTF-8//IGNORE’ is not allowed in /hyperf-skeleton/hyperf-winkar-mall-admin/vendor/aliyuncs/oss-sdk-php/src/OSS/OssClient.php on line 3075
详细参见这里: https://github.com/aliyun/aliyun-oss-php-sdk/issues/101
docker file 添加:
RUN apk --no-cache --allow-untrusted --repository http://dl-cdn.alpinelinux.org/alpine/edge/community/ add gnu-libiconv
ENV LD_PRELOAD /usr/lib/preloadable_libiconv.so php