Yii2 文件上传 returns UPLOAD_ERR_PARTIAL
Yii2 file upload returns UPLOAD_ERR_PARTIAL
创建新项目时图片上传失败,但在更新新创建的项目时,文件成功上传。有什么原因吗?
热门新闻模型
class TrendingNews extends \yii\db\ActiveRecord
{
const EVENT_ADD_TRENDING_NEWS = 'add-trending-news';
public $featuredFile;
public function init() {
$this->on(self::EVENT_ADD_TRENDING_NEWS, [$this, 'saveToLog']);
}
/**
* @inheritdoc
*/
public static function tableName()
{
return 'trending_news';
}
/**
* @inheritdoc
*/
public function rules()
{
return [
[['headline_text','news_info', 'news_url', 'author', 'published', 'date_added', 'date_modified'], 'required'],
[['headline_text', 'image_url', 'news_info', 'news_url'], 'string'],
[['date_added', 'date_modified'], 'safe'],
[['author'], 'string', 'max' => 20],
[['published'], 'string', 'max' => 2],
[['featuredFile'], 'file', 'skipOnEmpty' => false, 'extensions' => 'png, jpg'],
];
}
/**
* @inheritdoc
*/
public function attributeLabels()
{
return [
'id' => 'ID',
'headline_text' => 'Headline',
'image_url' => 'Image Url',
'news_info' => 'Source',
'news_url' => 'News Url',
'author' => 'Author',
'published' => 'Published',
'date_added' => 'Date Added',
'date_modified' => 'Date Modified',
'featuredFile' => 'Featured Image',
];
}
public function uploadBanner()
{
if ($this->validate()) {
$ymd = date("Ymd");
$save_path = \Yii::getAlias('@backend') . '/web/uploads/' . $ymd . '/';
if (!file_exists($save_path)) {
mkdir($save_path, 0777, true);
}
$fileName = "trending_".Yii::$app->security->generateRandomString(20);
$this->featuredFile->saveAs($save_path . $fileName .'.' . $this->featuredFile->extension);
$this->image_url = $ymd . '/'. $fileName . '.' . $this->featuredFile->extension;
return true;
} else {
return false;
}
}
public function upload()
{
if ($this->validate()) {
$ymd = date("Ymd");
$save_path = \Yii::getAlias('@backend') . '/web/uploads/' . $ymd . '/';
if (!file_exists($save_path)) {
mkdir($save_path, 0777, true);
}
$fileName = Yii::$app->security->generateRandomString(20);
$this->featuredFile->saveAs($save_path . $fileName .'.' . $this->featuredFile->extension);
$this->image_url = $ymd . '/'. $fileName . '.' . $this->featuredFile->extension;
return true;
} else {
return false;
}
}
public function beforeSave($insert)
{
if (parent::beforeSave($insert)) {
if ($this->isNewRecord) {
$this->date_added = date("YmdHis");
$this->author = Yii::$app->user->identity->id;
}
else {
$this->date_modified = date("YmdHis");
}
return true;
}
else{
return false;
}
}
public function saveToLog($event)
{
//assigning attributes
// echo 'mail sent to admin using the event';
$app_log_model = new AppLog();
$app_log_model->log_time = date("YmdHis");
$app_log_model->log_activity = 'Added a trending news';
$app_log_model->user_id = Yii::$app->user->identity->id;
$app_log_model->device = "1";
if ($app_log_model->save()) {
return true;
} else {
return $app_log_model->getErrors() ;
}
}
}
用法
public function actionCreate()
{
$model = new TrendingNews();
if ($model->load(Yii::$app->request->post())) {
$model->featuredFile = UploadedFile::getInstance($model, 'featuredFile');
if(isset($model->featuredFile)){
$model->upload();
$model->save(false);
} else {
// file is uploaded successfully
$model->save();
//$model->trigger(BlogArticle::EVENT_EDIT_ARTICLE);
}
return $this->redirect(['view', 'id' => $model->id]);
} else {
return $this->render('create', [
'model' => $model,
]);
}
}
public function actionUpdate($id)
{
$model = $this->findModel($id);
if ($model->load(Yii::$app->request->post())) {
$model->featuredFile = UploadedFile::getInstance($model, 'featuredFile');
if(isset($model->featuredFile)){
$model->upload();
$model->save(false);
} else {
$model->save();
}
return $this->redirect(['view', 'id' => $model->id]);
} else {
return $this->render('update', [
'model' => $model,
]);
}
}
应用程序日志显示了这一点
$_FILES = [
'TrendingNews' => [
'name' => [
'featuredFile' => 'another_evento.jpg'
]
'type' => [
'featuredFile' => ''
]
'tmp_name' => [
'featuredFile' => ''
]
'error' => [
'featuredFile' => 3
]
'size' => [
'featuredFile' => 0
]
]
]
featuredFile
不是数据库字段
有什么地方做错了吗?
我正在使用 xampp,在实时服务器上试过,问题是一样的
如果您必须在插入时要求输入文件而不是在更新时输入文件,那么您做错了,您应该为其添加一个方案,以便它仅在添加新记录时要求您提供文件。
其次,您正在使用相同的 ActiveRecord
模型并在其中添加了一个自定义属性以用作文件输入,并且在您调用 validate()
并返回的 upload()
函数中false 如果没有验证但同时你没有在你的控制器操作中检查 true
或 false
并且在下一行你用 false 调用 $model->save(false)
所以技术上你的脚本会如果有任何验证错误,永远不要告诉用户。
文件应该在保存记录之后上传,而不是在保存记录之前上传,这样就不会在出现错误时上传额外的文件,尽管您希望在 insert
上需要文件,所以从技术上讲,如果文件未上传,记录不应保存,因此我们有数据库插入事务,您应该使用事务块来保存 rcord 和文件
如果您有一个单独的 FormModel
用于文件上传,您应该只调用 validate()
方法进行文件上传,否则您应该从 UploadedFile
加载实例到模型字段和调用 $model->save()
它将在保存之前自动验证模型,您应该在上传之前检查空文件名,这样当您更新任何记录而不提交文件时,前一个文件应该保持原样。
您需要先将验证规则更新为以下内容
/**
* @inheritdoc
*/
public function rules()
{
return [
[['headline_text','news_info', 'news_url', 'author', 'published', 'date_added', 'date_modified'], 'required'],
[['headline_text', 'image_url', 'news_info', 'news_url'], 'string'],
[['date_added', 'date_modified'], 'safe'],
[['author'], 'string', 'max' => 20],
[['published'], 'string', 'max' => 2],
[ [ 'featuredFile' ] , 'required' , 'on' => 'insert' ] ,
[ [ 'featuredFile' ] , 'file' , 'extensions' => 'png, jpg' , 'maxSize' => 200000 , 'tooBig' => 'Limit is 500KB' ] ,
];
}
将upload()
函数改成下面的
public function upload( $ymd , $fileName ) {
if ( $this->featuredFile !== null && $this->featuredFile->name !== '' ) {
$save_path = \Yii::getAlias ( '@backend' ) . '/web/uploads/' . $ymd . '/';
if ( !file_exists ( $save_path ) ) {
mkdir ( $save_path , 0777 , true );
}
if ( !$this->featuredFile->saveAs ( $save_path . $fileName ) ) {
$this->addError ( 'featuredFile' , 'File could not be uploaded' );
throw new \Exception ( 'File upload error' );
}
}
}
然后在模型中添加另一种方法,以在 update
上传新文件时删除旧文件
public function unlinkOldFile( $filename ) {
if ( $filename !== '' ) {
$save_path = \Yii::getAlias ( '@backend' ) . '/web/uploads/' . $filename;
unlink ( $save_path );
}
}
之后将您的 create
和 update
操作更改为以下内容,以便它们使用 transation
块进行数据库操作
public function actionCreate() {
$model = new TrendingNews(['scenario'=>'insert']);
if ( $model->load ( Yii::$app->request->post () ) ) {
$model->featuredFile = UploadedFile::getInstance ( $model , 'featuredFile' );
if ( $model->featuredFile !== null ) {
$ymd = date ( "Ymd" );
$fileName = Yii::$app->security->generateRandomString ( 20 ) . '.' . $model->featuredFile->extension;
$model->image_url = $ymd . '/' . $fileName;
}
$transaction = Yii::$app->db->beginTransaction ();
try {
if ( !$model->save () ) {
throw new \Exception ( 'Error Occoured' );
}
$model->upload ( $ymd , $fileName );
$transaction->commit ();
return $this->redirect ( [ 'view' , 'id' => $model->id ] );
} catch ( \Exception $ex ) {
$transaction->rollBack ();
}
}
return $this->render ( 'create' , [
'model' => $model ,
] );
}
public function actionUpdate( $id ) {
$model = $this->findModel ( $id );
if ( $model->load ( Yii::$app->request->post () ) ) {
$model->featuredFile = UploadedFile::getInstance ( $model , 'featuredFile' );
//$oldFile = '';
$oldFile = $model->image_url;
if ( $model->featuredFile !== null ) {
$ymd = date ( "Ymd" );
$fileName = Yii::$app->security->generateRandomString ( 20 ) . '.' . $model->featuredFile->extension;
$model->image_url = $ymd . '/' . $fileName;
}
$transaction = Yii::$app->db->beginTransaction ();
try {
if ( !$model->save () ) {
throw new \Exception ( 'Model error' );
}
$model->upload ( $ymd , $fileName );
$model->unlinkOldFile ( $oldFile );
$transaction->commit ();
return $this->redirect ( [ 'view' , 'id' => $model->id ] );
} catch ( Exception $ex ) {
$transaction->rollBack ();
}
}
return $this->render ( 'update' , [
'model' => $model ,
] );
}
创建新项目时图片上传失败,但在更新新创建的项目时,文件成功上传。有什么原因吗?
热门新闻模型
class TrendingNews extends \yii\db\ActiveRecord
{
const EVENT_ADD_TRENDING_NEWS = 'add-trending-news';
public $featuredFile;
public function init() {
$this->on(self::EVENT_ADD_TRENDING_NEWS, [$this, 'saveToLog']);
}
/**
* @inheritdoc
*/
public static function tableName()
{
return 'trending_news';
}
/**
* @inheritdoc
*/
public function rules()
{
return [
[['headline_text','news_info', 'news_url', 'author', 'published', 'date_added', 'date_modified'], 'required'],
[['headline_text', 'image_url', 'news_info', 'news_url'], 'string'],
[['date_added', 'date_modified'], 'safe'],
[['author'], 'string', 'max' => 20],
[['published'], 'string', 'max' => 2],
[['featuredFile'], 'file', 'skipOnEmpty' => false, 'extensions' => 'png, jpg'],
];
}
/**
* @inheritdoc
*/
public function attributeLabels()
{
return [
'id' => 'ID',
'headline_text' => 'Headline',
'image_url' => 'Image Url',
'news_info' => 'Source',
'news_url' => 'News Url',
'author' => 'Author',
'published' => 'Published',
'date_added' => 'Date Added',
'date_modified' => 'Date Modified',
'featuredFile' => 'Featured Image',
];
}
public function uploadBanner()
{
if ($this->validate()) {
$ymd = date("Ymd");
$save_path = \Yii::getAlias('@backend') . '/web/uploads/' . $ymd . '/';
if (!file_exists($save_path)) {
mkdir($save_path, 0777, true);
}
$fileName = "trending_".Yii::$app->security->generateRandomString(20);
$this->featuredFile->saveAs($save_path . $fileName .'.' . $this->featuredFile->extension);
$this->image_url = $ymd . '/'. $fileName . '.' . $this->featuredFile->extension;
return true;
} else {
return false;
}
}
public function upload()
{
if ($this->validate()) {
$ymd = date("Ymd");
$save_path = \Yii::getAlias('@backend') . '/web/uploads/' . $ymd . '/';
if (!file_exists($save_path)) {
mkdir($save_path, 0777, true);
}
$fileName = Yii::$app->security->generateRandomString(20);
$this->featuredFile->saveAs($save_path . $fileName .'.' . $this->featuredFile->extension);
$this->image_url = $ymd . '/'. $fileName . '.' . $this->featuredFile->extension;
return true;
} else {
return false;
}
}
public function beforeSave($insert)
{
if (parent::beforeSave($insert)) {
if ($this->isNewRecord) {
$this->date_added = date("YmdHis");
$this->author = Yii::$app->user->identity->id;
}
else {
$this->date_modified = date("YmdHis");
}
return true;
}
else{
return false;
}
}
public function saveToLog($event)
{
//assigning attributes
// echo 'mail sent to admin using the event';
$app_log_model = new AppLog();
$app_log_model->log_time = date("YmdHis");
$app_log_model->log_activity = 'Added a trending news';
$app_log_model->user_id = Yii::$app->user->identity->id;
$app_log_model->device = "1";
if ($app_log_model->save()) {
return true;
} else {
return $app_log_model->getErrors() ;
}
}
}
用法
public function actionCreate()
{
$model = new TrendingNews();
if ($model->load(Yii::$app->request->post())) {
$model->featuredFile = UploadedFile::getInstance($model, 'featuredFile');
if(isset($model->featuredFile)){
$model->upload();
$model->save(false);
} else {
// file is uploaded successfully
$model->save();
//$model->trigger(BlogArticle::EVENT_EDIT_ARTICLE);
}
return $this->redirect(['view', 'id' => $model->id]);
} else {
return $this->render('create', [
'model' => $model,
]);
}
}
public function actionUpdate($id)
{
$model = $this->findModel($id);
if ($model->load(Yii::$app->request->post())) {
$model->featuredFile = UploadedFile::getInstance($model, 'featuredFile');
if(isset($model->featuredFile)){
$model->upload();
$model->save(false);
} else {
$model->save();
}
return $this->redirect(['view', 'id' => $model->id]);
} else {
return $this->render('update', [
'model' => $model,
]);
}
}
应用程序日志显示了这一点
$_FILES = [
'TrendingNews' => [
'name' => [
'featuredFile' => 'another_evento.jpg'
]
'type' => [
'featuredFile' => ''
]
'tmp_name' => [
'featuredFile' => ''
]
'error' => [
'featuredFile' => 3
]
'size' => [
'featuredFile' => 0
]
]
]
featuredFile
不是数据库字段
有什么地方做错了吗?
我正在使用 xampp,在实时服务器上试过,问题是一样的
如果您必须在插入时要求输入文件而不是在更新时输入文件,那么您做错了,您应该为其添加一个方案,以便它仅在添加新记录时要求您提供文件。
其次,您正在使用相同的 ActiveRecord
模型并在其中添加了一个自定义属性以用作文件输入,并且在您调用 validate()
并返回的 upload()
函数中false 如果没有验证但同时你没有在你的控制器操作中检查 true
或 false
并且在下一行你用 false 调用 $model->save(false)
所以技术上你的脚本会如果有任何验证错误,永远不要告诉用户。
文件应该在保存记录之后上传,而不是在保存记录之前上传,这样就不会在出现错误时上传额外的文件,尽管您希望在 insert
上需要文件,所以从技术上讲,如果文件未上传,记录不应保存,因此我们有数据库插入事务,您应该使用事务块来保存 rcord 和文件
如果您有一个单独的 FormModel
用于文件上传,您应该只调用 validate()
方法进行文件上传,否则您应该从 UploadedFile
加载实例到模型字段和调用 $model->save()
它将在保存之前自动验证模型,您应该在上传之前检查空文件名,这样当您更新任何记录而不提交文件时,前一个文件应该保持原样。
您需要先将验证规则更新为以下内容
/**
* @inheritdoc
*/
public function rules()
{
return [
[['headline_text','news_info', 'news_url', 'author', 'published', 'date_added', 'date_modified'], 'required'],
[['headline_text', 'image_url', 'news_info', 'news_url'], 'string'],
[['date_added', 'date_modified'], 'safe'],
[['author'], 'string', 'max' => 20],
[['published'], 'string', 'max' => 2],
[ [ 'featuredFile' ] , 'required' , 'on' => 'insert' ] ,
[ [ 'featuredFile' ] , 'file' , 'extensions' => 'png, jpg' , 'maxSize' => 200000 , 'tooBig' => 'Limit is 500KB' ] ,
];
}
将upload()
函数改成下面的
public function upload( $ymd , $fileName ) {
if ( $this->featuredFile !== null && $this->featuredFile->name !== '' ) {
$save_path = \Yii::getAlias ( '@backend' ) . '/web/uploads/' . $ymd . '/';
if ( !file_exists ( $save_path ) ) {
mkdir ( $save_path , 0777 , true );
}
if ( !$this->featuredFile->saveAs ( $save_path . $fileName ) ) {
$this->addError ( 'featuredFile' , 'File could not be uploaded' );
throw new \Exception ( 'File upload error' );
}
}
}
然后在模型中添加另一种方法,以在 update
public function unlinkOldFile( $filename ) {
if ( $filename !== '' ) {
$save_path = \Yii::getAlias ( '@backend' ) . '/web/uploads/' . $filename;
unlink ( $save_path );
}
}
之后将您的 create
和 update
操作更改为以下内容,以便它们使用 transation
块进行数据库操作
public function actionCreate() {
$model = new TrendingNews(['scenario'=>'insert']);
if ( $model->load ( Yii::$app->request->post () ) ) {
$model->featuredFile = UploadedFile::getInstance ( $model , 'featuredFile' );
if ( $model->featuredFile !== null ) {
$ymd = date ( "Ymd" );
$fileName = Yii::$app->security->generateRandomString ( 20 ) . '.' . $model->featuredFile->extension;
$model->image_url = $ymd . '/' . $fileName;
}
$transaction = Yii::$app->db->beginTransaction ();
try {
if ( !$model->save () ) {
throw new \Exception ( 'Error Occoured' );
}
$model->upload ( $ymd , $fileName );
$transaction->commit ();
return $this->redirect ( [ 'view' , 'id' => $model->id ] );
} catch ( \Exception $ex ) {
$transaction->rollBack ();
}
}
return $this->render ( 'create' , [
'model' => $model ,
] );
}
public function actionUpdate( $id ) {
$model = $this->findModel ( $id );
if ( $model->load ( Yii::$app->request->post () ) ) {
$model->featuredFile = UploadedFile::getInstance ( $model , 'featuredFile' );
//$oldFile = '';
$oldFile = $model->image_url;
if ( $model->featuredFile !== null ) {
$ymd = date ( "Ymd" );
$fileName = Yii::$app->security->generateRandomString ( 20 ) . '.' . $model->featuredFile->extension;
$model->image_url = $ymd . '/' . $fileName;
}
$transaction = Yii::$app->db->beginTransaction ();
try {
if ( !$model->save () ) {
throw new \Exception ( 'Model error' );
}
$model->upload ( $ymd , $fileName );
$model->unlinkOldFile ( $oldFile );
$transaction->commit ();
return $this->redirect ( [ 'view' , 'id' => $model->id ] );
} catch ( Exception $ex ) {
$transaction->rollBack ();
}
}
return $this->render ( 'update' , [
'model' => $model ,
] );
}