Yii的上传问题及解决
这些天在学习YiiFramework,感觉很对自己胃口,加上原来学过rails,所以理解Yii的许多概念很容易。
期间遇到一个问题,就是上传文件字段的问题。
有个表TblDocument,其中有一个字段为real_filename,保存用户上传后的文件在服务器实际保存的文件名。
看资料可知,Yii中有一个CUploadedFile可以直接用。按照官网上的Wiki文章,慢慢搞定了上传和保存。过程如下:
1、在Model文件中的rules()段里增加一行
array('real_filename', 'file', 'types'=>'jpg', 'maxSize'=>307200, 'allowEmpty'=>TRUE),
2、在model引用到的_form.php里,相关引用改为:
<div class="row">
<?php echo $form->labelEx($model,'real_filename'); ?>
<?php echo $form->fileField($model,'real_filename',array('size'=>60,'maxlength'=>255)); ?>
<?php echo $form->error($model,'real_filename'); ?>
</div>
(gii生成的是textfield)
3、在controller中这样写
public function actionUpdate($id)
{
$folder='/upload/';
$root=YiiBase::getPathOfAlias('webroot');
$model=$this->loadModel($id);
$old_real_filename=$model->real_filename;
// Uncomment the following line if AJAX validation is needed
// $this->performAjaxValidation($model);
if(isset($_POST['TblDocument']))
{
$model->attributes=$_POST['TblDocument'];
$real_filename = CUploadedFile::getInstance($model, 'real_filename');
$newName=date('Ymd-His-').rand(1000,9999).'.'.$real_filename->extensionName;
if (is_object($real_filename)) {
$real_filename->saveAs($root.$folder.$newName);
$model->real_filename=$newName;
}
$model->save();
$this->redirect(array('view', 'id'=>$model->id));
}
$this->render('update',array(
'model'=>$model,
));
}
这样,文件上传后,会正确地放入指定文件夹中,名字也生成正确,没有问题。
不过在进入记录修改时,遇到了一个困扰几天的问题:修改这个表的一条记录,当只是修改那些非文件上传字段时,始终改不过来。试着把controller的$model->save()后面的redirect转向去掉,这样,save后会继续回到update的视图,我看到有一行错误信息:大意是real_filename不可以为空。这样就明白了,原来,在save之前,有一个内置的合法性验证,Yii发现有错误,就制止了save,所以记录就没有被修改。
观察update时的html源码,发现Yii在处理上传文件字段时,用了这样的代码:
<div class="row">
<label for="TblDocument_real_filename">原始文件名</label>
<input id="ytTblDocument_real_filename" type="hidden" value="" name="TblDocument[real_filename]" />
<input size="60" maxlength="255" name="TblDocument[real_filename]" id="TblDocument_real_filename" type="file" />
</div>
看到里面有一个hidden字段,name和file field相同,都是TblDocument[real_filename]。能不能在显示form时,先悄悄将它赋好值,这样提交时,岂不是就解决了real_filename不能为空的错误?
说干就干,我还用上了jquery,在网页中动态修改了它的值。(因为这个hidden字段是yii自动生成的,我假装一开始不知道它的名字,这就是为什么要用jquery的原因--主要是通过jquery的选择器,可以容易地定位和修改它)。
好了,那个亲爱的hidden字段现在成功加载了本条记录的原始real_filename的值,提交时经过wexpert监测,也真的有提交,可是可是,还是出现同样的错误。。。
。。。
我试着在model的rules里删除那行对file字段的定义,错误提示神奇的消失了。
现在症结已经很清楚了,就是字段定义方面的问题。继续查文档,看到有一个allowEmpty属性。就是专门管这事儿的。最后,我把那一行改为
array('real_filename', 'file', 'types'=>'jpg', 'maxSize'=>307200, 'allowEmpty'=>TRUE),
大功告成,亲个嘴儿吧~
========================
总结,这个问题开始卡壳,是因为对Yii的处理机制、调试方法、各种调用都不熟悉的原因,在查找原因的过程中,也算是多方都有小的收获,最后问题解决。可惜的是耽误了好几天时间。