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的处理机制、调试方法、各种调用都不熟悉的原因,在查找原因的过程中,也算是多方都有小的收获,最后问题解决。可惜的是耽误了好几天时间。

posted on 2011-10-11 07:31  anjo  阅读(3041)  评论(1编辑  收藏  举报