1、上传文件的接口,之有仅实现了 上传选题素材 的场景,现在需要新增 上传基地图标 的场景,决定复用上传文件的接口,如图1
2、新增请求参数,scenario:可选,场景,default:默认;config_base_location_icon:基地设置的图标,默认:default
3、编辑 /api/rests/asset/UploadAction.php,场景通过构造初始化配置来设置
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace api/rests/asset;
use Yii;
use api/models/Upload;
use api/services/AssetService;
use yii/base/Exception;
use yii/base/Model;
use yii/web/UnprocessableEntityHttpException;
use yii/web/UploadedFile;
use yii/web/ServerErrorHttpException;
/**
* 上传资源:/assets/upload(asset/upload)
*
* 1、请求参数列表
* (1)files[]:必填,上传的文件
* (2)scenario:可选,场景,default:默认;config_base_location_icon:基地设置的图标,默认:default
*
* 2、输入数据验证规则
* (1)必填:files[]
* (2)文件
* A、可接受上传的文件扩展名列表
* B、可接受上传的 MIME 类型列表
* C、上传文件所需最少多少 Byte 的大小
* D、上传文件所需最多多少 Byte 的大小
* E、给定属性最多能承载多少个文件
* (3)范围(['default', 'config_base_location_icon']):scenario
*
* 3、操作数据
* (1)上传文件至临时的资源目录
*
* UploadAction implements the API endpoint for creating a new model from the given data.
*
* For more details and usage information on UploadAction, see the [guide article on rest controllers](guide:rest-controllers).
*
* @author Qiang Wang <shuijingwanwq@163.com>
* @since 1.0
*/
class UploadAction extends Action
{
/**
* @var string the scenario to be assigned to the new model before it is validated and saved.
*/
public $scenario = Model::SCENARIO_DEFAULT;
/**
* @var string the name of the view action. This property is need to create the URL when the model is successfully created.
*/
public $viewAction = 'view';
/**
* Uploads a new model.
* @return array the model newly uploaded
* @throws ServerErrorHttpException 如果创建目录失败,将抛出 500 HTTP 异常
* @throws ServerErrorHttpException if there is any error when creating the model
* @throws Exception if the directory could not be created (i.e. php error due to parallel changes)
*/
public function run()
{
if ($this->checkAccess) {
call_user_func($this->checkAccess, $this->id);
}
$request = Yii::$app->request;
$scenario = $request->post('scenario', $this->scenario);
/* 验证场景的范围(['default', 'config_base_location_icon']) */
if (!in_array($scenario, [$this->scenario, Upload::SCENARIO_CONFIG_BASE_LOCATION_ICON])) {
throw new UnprocessableEntityHttpException(Yii::t('error', Yii::t('error', Yii::t('error', '226076'), ['scenario' => $scenario])), 226076);
}
/* @var $model Upload */
$model = new Upload(['scenario' => $scenario]);
// 将 UploadedFile 实例数组赋值给 Upload::files
$model->files = UploadedFile::getInstances($model, 'files');
if ($model->validate()) {
$assetService = new AssetService();
$result = $assetService->uploadTempAssets($model->files);
return ['code' => 10000, 'message' => Yii::t('success', '126033'), 'data' => ['items' => $result]];
} elseif ($model->hasErrors()) {
$response = Yii::$app->getResponse();
$response->setStatusCode(422, 'Data Validation Failed.');
$firstError = '';
foreach ($model->getFirstErrors() as $message) {
$firstError = $message;
break;
}
return ['code' => 226004, 'message' => Yii::t('error', Yii::t('error', Yii::t('error', '226004'), ['first_error' => $firstError]))];
} elseif (!$model->hasErrors()) {
throw new ServerErrorHttpException('Failed to upload the object for unknown reason.');
}
}
}
4、编辑 /common/logics/Upload.php,通过指定规则的 on 属性,一条规则可以只在某个 场景 下应用,以区分不同场景下的验证规则。例:上传选题素材为默认的场景,上传基地图标为基地设置的图标的场景。
<?php
namespace common/logics;
use Yii;
use yii/base/Model;
use yii/web/UploadedFile;
class Upload extends Model
{
const SCENARIO_CONFIG_BASE_LOCATION_ICON = 'config_base_location_icon'; // 场景:基地设置的图标
/**
* @var UploadedFile
*/
public $files;
/**
* {@inheritdoc}
*/
public function scenarios()
{
$scenarios = parent::scenarios();
return $scenarios;
}
public function rules()
{
return [
[['files'], 'image', 'skipOnEmpty' => false, 'extensions' => Yii::$app->params['pcsApi']['asset']['upload']['scenario']['configBaseLocationIcon']['extensions'], 'mimeTypes' => Yii::$app->params['pcsApi']['asset']['upload']['scenario']['configBaseLocationIcon']['mimeTypes'], 'minSize' => Yii::$app->params['pcsApi']['asset']['upload']['scenario']['configBaseLocationIcon']['minSize'], 'maxSize' => Yii::$app->params['pcsApi']['asset']['upload']['scenario']['configBaseLocationIcon']['maxSize'], 'maxFiles' => Yii::$app->params['pcsApi']['asset']['upload']['scenario']['configBaseLocationIcon']['maxFiles'], 'minWidth' => Yii::$app->params['pcsApi']['asset']['upload']['scenario']['configBaseLocationIcon']['minWidth'], 'maxWidth' => Yii::$app->params['pcsApi']['asset']['upload']['scenario']['configBaseLocationIcon']['maxWidth'], 'minHeight' => Yii::$app->params['pcsApi']['asset']['upload']['scenario']['configBaseLocationIcon']['minHeight'], 'maxHeight' => Yii::$app->params['pcsApi']['asset']['upload']['scenario']['configBaseLocationIcon']['maxHeight'], 'on' => self::SCENARIO_CONFIG_BASE_LOCATION_ICON],
[['files'], 'file', 'skipOnEmpty' => false, 'extensions' => Yii::$app->params['pcsApi']['asset']['upload']['extensions'], 'mimeTypes' => Yii::$app->params['pcsApi']['asset']['upload']['mimeTypes'], 'minSize' => Yii::$app->params['pcsApi']['asset']['upload']['minSize'], 'maxSize' => Yii::$app->params['pcsApi']['asset']['upload']['maxSize'], 'maxFiles' => Yii::$app->params['pcsApi']['asset']['upload']['maxFiles']],
];
}
public function formName()
{
return '';
}
}
5、验证规则的具体参数配置在文件 /common/config/params-local.php
// 策划指挥系统接口
'pcsApi' => [
'asset' => [ // 资源
'basePath' => 'E:/wwwroot/pcs-api/storage', // BASE PATH
'tempDir' => '/tmp', // TEMP DIR
'hostInfo' => 'http://127.0.0.1/pcs-api/storage', // HOME URL
'baseUrl' => '', // BASE URL
'upload' => [ // 上传
'extensions' => 'ogg, pdf, xml, zip, gz, mp4, mp3, wav, webm, gif, jpeg, jpg, png, webp, svg, svgz, tiff, css, csv, txt, vcf, vcard, mov, qt, mkv, mk3d, mka, mks, wmv, flv', // 可接受上传的文件扩展名列表
'mimeTypes' => 'application/ogg, application/pdf, application/xml, application/zip, application/gzip, audio/mp4, audio/mpeg, audio/ogg, audio/vnd.wave, audio/webm, image/gif, image/jpeg, image/png, image/webp, image/svg+xml, image/tiff, text/css, text/csv, text/plain, text/vcard, text/xml, video/mpeg, video/mp4, video/ogg, video/quicktime, video/webm, video/x-matroska, video/x-ms-wmv, video/x-flv', // 可接受上传的 MIME 类型列表
'minSize' => null, // 上传文件所需最少多少 Byte 的大小
'maxSize' => 1024 * 1024 * 1024, // 上传文件所需最多多少 Byte 的大小
'maxFiles' => 10, // 给定属性最多能承载多少个文件
'scenario' => [ // 场景
'configBaseLocationIcon' => [ // 基地设置的图标
'extensions' => 'jpeg, jpg, png', // 可接受上传的文件扩展名列表
'mimeTypes' => 'image/jpeg, image/png', // 可接受上传的 MIME 类型列表
'minSize' => null, // 上传文件所需最少多少 Byte 的大小
'maxSize' => 1024 * 1024 * 2, // 上传文件所需最多多少 Byte 的大小
'maxFiles' => 2, // 给定属性最多能承载多少个文件
'minWidth' => 50, // 图片的最小宽度
'maxWidth' => 200, // 图片的最大宽度
'minHeight' => 50, // 图片的最小高度
'maxHeight' => 200, // 图片的最大高度
],
],
],
],
],
6、上传选题素材 的场景,文件扩展名为 zip 的文件,上传成功,符合预期,如图2
7、基地设置的图标 的场景,文件扩展名为 zip 的文件,上传失败,符合预期,如图3
8、maxFiles:给定属性最多能承载多少个文件。 默认为 1,代表只允许单文件上传。 若值大于一,那么输入值必须为包含最多 maxFiles 个上传文件元素的数组。基地设置的图标 的场景,上传文件的数量应该只能够为 1,现在 maxFiles:2,即可最多上传 2 个文件,原因在于 maxFiles:1 时,响应失败,如图4
9、在不同场景中,一些场景中文件数量只能够为 1 个,一些场景中文件数量可以为多个,现在 maxFiles:2,即可最多上传 2 个文件,如图5
10、编辑 /api/rests/asset/UploadAction.php,判断场景,如果为:config_base_location_icon,则上传单个文件(即第 1 个文件),现在 maxFiles:2,即可最多上传 2 个文件(2 个文件皆会验证,但仅会上传第 1 个文件),符合预期(其实此处最佳的方案应该是响应失败,提示仅能够上传一个文件的,但是却是需要再实现一个上传的接口,有所冗余,因此,最终决定,还是复用),如图6
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace api/rests/asset;
use Yii;
use api/models/Upload;
use api/services/AssetService;
use yii/base/Exception;
use yii/base/Model;
use yii/web/UnprocessableEntityHttpException;
use yii/web/UploadedFile;
use yii/web/ServerErrorHttpException;
/**
* 上传资源:/assets/upload(asset/upload)
*
* 1、请求参数列表
* (1)files[]:必填,上传的文件
* (2)scenario:可选,场景,default:默认;config_base_location_icon:基地设置的图标,默认:default
*
* 2、输入数据验证规则
* (1)必填:files[]
* (2)文件
* A、可接受上传的文件扩展名列表
* B、可接受上传的 MIME 类型列表
* C、上传文件所需最少多少 Byte 的大小
* D、上传文件所需最多多少 Byte 的大小
* E、给定属性最多能承载多少个文件
* (3)范围(['default', 'config_base_location_icon']):scenario
*
* 3、操作数据
* (1)上传文件至临时的资源目录
*
* UploadAction implements the API endpoint for creating a new model from the given data.
*
* For more details and usage information on UploadAction, see the [guide article on rest controllers](guide:rest-controllers).
*
* @author Qiang Wang <shuijingwanwq@163.com>
* @since 1.0
*/
class UploadAction extends Action
{
/**
* @var string the scenario to be assigned to the new model before it is validated and saved.
*/
public $scenario = Model::SCENARIO_DEFAULT;
/**
* @var string the name of the view action. This property is need to create the URL when the model is successfully created.
*/
public $viewAction = 'view';
/**
* Uploads a new model.
* @return array the model newly uploaded
* @throws ServerErrorHttpException 如果创建目录失败,将抛出 500 HTTP 异常
* @throws ServerErrorHttpException if there is any error when creating the model
* @throws Exception if the directory could not be created (i.e. php error due to parallel changes)
*/
public function run()
{
if ($this->checkAccess) {
call_user_func($this->checkAccess, $this->id);
}
$request = Yii::$app->request;
$scenario = $request->post('scenario', $this->scenario);
/* 验证场景的范围(['default', 'config_base_location_icon']) */
if (!in_array($scenario, [$this->scenario, Upload::SCENARIO_CONFIG_BASE_LOCATION_ICON])) {
throw new UnprocessableEntityHttpException(Yii::t('error', Yii::t('error', Yii::t('error', '226076'), ['scenario' => $scenario])), 226076);
}
/* @var $model Upload */
$model = new Upload(['scenario' => $scenario]);
// 将 UploadedFile 实例数组赋值给 Upload::files
$model->files = UploadedFile::getInstances($model, 'files');
if ($model->validate()) {
$assetService = new AssetService();
/* 判断场景,如果为:config_base_location_icon,则上传单个文件(即第 1 个文件) */
if ($scenario == Upload::SCENARIO_CONFIG_BASE_LOCATION_ICON) {
// 将 UploadedFile 实例赋值给 Upload::files
$model->files = [$model->files[0]];
}
$result = $assetService->uploadTempAssets($model->files);
return ['code' => 10000, 'message' => Yii::t('success', '126033'), 'data' => ['items' => $result]];
} elseif ($model->hasErrors()) {
$response = Yii::$app->getResponse();
$response->setStatusCode(422, 'Data Validation Failed.');
$firstError = '';
foreach ($model->getFirstErrors() as $message) {
$firstError = $message;
break;
}
return ['code' => 226004, 'message' => Yii::t('error', Yii::t('error', Yii::t('error', '226004'), ['first_error' => $firstError]))];
} elseif (!$model->hasErrors()) {
throw new ServerErrorHttpException('Failed to upload the object for unknown reason.');
}
}
}
原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/tech/pnotes/250482.html
