Yii PHP file uploader overwriting on update - php

I have a basic form in PHP framework Yii, the action to create works fine, however, when i update the record (for example if i'm not changing the file upload, but another field), it overwrites the file upload and blanks it, can anyone assist me? I've tried all the validation I can think of around the controller items, but no matter what i add it still blanks it on update.
Here's the view code
<?php $form=$this->beginWidget('booster.widgets.TbActiveForm', array(
'id'=>'company-form',
'enableAjaxValidation'=>false,
'method' => 'post',
'type' => 'horizontal',
'htmlOptions' => array(
'enctype' => 'multipart/form-data'
)
));
echo $form->textFieldGroup($model,'name',array('class'=>'col-md-5','maxlength'=>75));
echo $form->fileFieldGroup($model, 'logo',
array(
'wrapperHtmlOptions' => array(
'class' => 'col-md-9',
),
'hint' => 'You can only upload jpg, png, gif\'s – max upload filesize is 1.5mb. Square images are advised.<br/>In certain browsers, you can also drag \' drop files into the dropzone.',
)
);
if($model->isNewRecord!='1'){ ?>
<div class="row">
<label class="col-md-3 control-label" style="padding-top: 25px;">Company image</label>
<div class="col-md-6">
<?php echo CHtml::image(Yii::app()->request->baseUrl.'/images/portraits/company/'.$model->logo,"logo",array("class"=>"img-polaroid placeholder")); ?>
</div>
</div>
<?php } ?>
And this is my actionUpdate function in Controller
public function actionUpdate($id)
{
$model=$this->loadModel($id);
if(isset($_POST['Company']))
{
$model->attributes=$_POST['Company'];
$uploadedFile=CUploadedFile::getInstance($model,'logo');
if (is_object($uploadedFile) && get_class($uploadedFile)==='CUploadedFile'){
if(!$uploadedFile == null){
$rnd = rand(0,9999);
$filename_preg1 = preg_replace("/[^a-zA-Z0-9.]/", '', "{$uploadedFile}");
$fileName = "{$rnd}-{$filename_preg1}";
$company = $model->name;
$model->logo = $fileName;
}
if($model->save()){
if(!empty($uploadedFile)){
$fullPath = Yii::app()->basePath . '/../images/portraits/company/' . $fileName;
$uploadedFile->saveAs($fullPath);
}
$this->redirect(array('view','id'=>$model->company_id));
}
}
if($model->save()){
$this->redirect(array('view','id'=>$model->company_id));
}
}
$this->render('update',array(
'model'=>$model,
));
}
Can anyone see where i'm going wrong?
UPDATE
Thanks SiZE, the code you gave me worked in one form and not in the other, the one it didn't work in has validation in the model rules
array('logo', 'file','types'=>'jpg, gif, png', 'allowEmpty'=>true, 'on'=>'update'),
This only works with the allowEmpty param here as it's not a required field, however, with the rule in place in the model, it still blanks the file field regardless, anyone have any more thoughts?

CActiveForm calls CHtml::activeFileField method wich generates empty hidden field to correctly work with model's rules.
You can try this:
$model=$this->loadModel($id);
$original_logo = $model->logo;
if(isset($_POST['Company'])) {
$model->attributes = $_POST['Company'];
$logo = CUploadedFile::getInstance($model, 'logo');
$model->logo = $logo !== null ? $logo->getName() : $original_logo;
if ($model->save()) {
if ($logo !== null) {
$logo->saveAs(/* specify path with file name here */);
}
$this->redirect(array('view','id'=>$model->company_id));
}
}

Related

Yii cant validate file input

I'm currently doing a project in PHP Yii Framework. I have a form which requires the user to upload a file. During the registration, user uploaded the file, however, when user submits the form, the form is always detected blank on the file input, it's like as if there is no attachment on the form. below is the code:
Model - CandidateResume:
return array(
array('resume_file','file','types'=>'doc,docx,pdf', 'allowEmpty'=>true, 'safe'=>true, 'on'=>'register'),
);
Model - Candidate:
return array(
array('can_email,name,repeat_can_email, can_password,repeat_can_password','required', 'on'=>'simplereg'),
);
View:
$form = $this->beginWidget('bootstrap.widgets.TbActiveForm',array(
'id'=>'candidate-form',
'enableAjaxValidation'=>true,
'type'=>'horizontal',
'htmlOptions' => array(
'enctype' => 'multipart/form-data',
'autocomplete'=>'off', //turn off auto complete in FF
)
));
echo $form->textFieldRow($model,'can_email',array('class'=>'span5','maxlength'=>100));
echo $form->textFieldRow($model,'repeat_can_email',array('class'=>'span5','maxlength'=>100));
echo $form->passwordFieldRow($model,'can_password',array('class'=>'span5','maxlength'=>100));
echo $form->passwordFieldRow($model,'repeat_can_password',array('class'=>'span5','maxlength'=>100));
echo $form->fileFieldRow($resume,'resume_file', array('id'=>'resume_file'));
$this->endWidget();
Controller - Candidate:
public function actionCreate()
{
$model = new Candidate();
$model->setScenario('simplereg');
$resume = new CandidateResume();
$resume->setScenario('register');
// Uncomment the following line if AJAX validation is needed
//$this->performAjaxValidation($model);
if(isset($_POST['Candidate'], $_POST['CandidateResume']))
{
$_POST['CandidateResume']['resume_file'] = $resume->resume_file;
$model->attributes = $_POST['Candidate'];
$resume->attributes = $_POST['CandidateResume'];
$uploadedFile = CUploadedFile::getInstance($resume,'resume_file');
if($resume->validate() && $model->validate())
{
$model->save();
if(!empty($uploadedFile)) // check if uploaded file is set or not
{
$saved = $uploadedFile->saveAs(Yii::app()->params['RESUME_PATH'].$model->can_id.'_'.$uploadedFile->getName());
$resume->resume_file = Yii::app()->params['RESUME_DIR'].$model->can_id.'_'.$uploadedFile->getName();
$resume->resume_send_ip = Yii::app()->request->userHostAddress;
}
$resume->save();
}
}
$this->render('create',array('model'=>$model, 'resume'=>$resume));
}
If I remove the validation on the controller:
if($resume->validate() && $model->validate())
The form data can be saved and attachment is placed properly in the folder. However, I need to do the validation for the form. Therefore I cant skip this part.
Is there anything that I missed out? I have checked many times and do researches for the solutions. All provides the similar solutions, therefore I can't figure out the things. Can anyone help me? Thank you in advance.
You don't set the resume_file attribute. It cames from $_FILES not from $_POST
$resume->attributes = $_POST['CandidateResume'];
$uploadedFile = CUploadedFile::getInstance($resume,'resume_file');
$resume->resume_file = $uploadedFile; //add this line

Yii file field posting empty values

I am a newbie in Yii, and I am trying to make an upload form in Yii, Please i need help.
Once the form post data to the controller every other post value is posted except for the file value.
i even tried checking for Errors with var_dump($model->image); and it returned this Error string '' (length=0) specifying an empty string like an image wasn't even posted at all.
This is my controller
class TestController extends Controller
{
public function actionIndex()
{
$model=new Test;
if(isset($_POST['Test']))
{
$model->attributes=$_POST['Test'];
if($model->save()){
var_dump($model->getErrors());
if ($model->image){
var_dump($model->image);
$uploadedFile=CUploadedFile::getInstance($model,'image');
$fileName = date("Y_m_d_H_i_s").$uploadedFile;
$model->image = $fileName;
if(!empty($uploadedFile)) // check if uploaded file is set or not
{
$uploadedFile->saveAs(Yii::getPathOfAlias('webroot').'/imagefolder/'.$fileName);
}
}
}
}
}
}
And this is my View
<?php $form=$this->beginWidget('CActiveForm', array(
'id'=>'test-form',
'htmlOptions' => array('enctype' => 'multipart/form-data'),
'enableAjaxValidation'=>false,
)); ?>
<?php echo CHtml::activeFileField($model,'image',array('id'=>'primaryupload')); ?>
<?php echo CHtml::submitButton($model->isNewRecord ? 'UPLOAD' : 'UPLOAD',array('id'=>'submit','class'=>'btn')); ?>
<?php $this->endWidget(); ?>
Any help will be appreciated. Because i am really frusrated at this point.
If you are only new to Yii and not in PHP, than you may know that uploaded files goes via $_FILES global variable and not via $_POST global variable. So to get uploaded file, you use
$uploadedFile = CUploadedFile::getInstance($model, 'image');
So your final code looks like this:
$post = Yii::app()->request->getPost('Test');
if ($post) {
$model->attributes = $post;
$uploadedFile = CUploadedFile::getInstance($model, 'image');
if ($uploadedFile) {
$imageName = date("Y_m_d_H_i_s").$uploadedFile->name;
$model->image = $imageName;
if ($model->save()) {
$uploadedFile->saveAs(Yii::getPathOfAlias('webroot').'/imagefolder/'.$imageName );
}
}
I think you should use $_FILES['image'] instead of $model->image.
As an option, you can "hardcode" file attribute in your form. Just:
<input type="file" id="yourid" name="yourname" />
Then in YourController, where you are parsing your POST data you could directly access to $_FILES['yourname'].
Not an elegant way, but simple and fast.
P.S.: if you are using $this->beginWidget in your view, then you should add to parameters
$this->beginWidget('CActiveForm', array(
...
'htmlOptions'=>array(
'enctype'=>'multipart/form-data'
),
));

Yii Framework store/save submitted file to images folder

Hi, for the past 2 days i've been reading and reading lots of tutorials about saving files to folders in Yii, and neither of them have worked so far. I have the folowing form:
<div class="form">
<?php $form = $this->beginWidget('CActiveForm', array(
'htmlOptions' => array('enctype' => 'multipart/form-data')
)); ?>
<?php echo $form->errorSummary($model); ?>
<div class="row">
<?php echo $form->labelEx($model,'Binaryfile'); ?>
<?php echo $form->fileField($model,'uploadedFile'); ?>
<?php echo $form->error($model,'uploadedFile'); ?>
</div>
<div class="row buttons">
<?php echo CHtml::submitButton($model->isNewRecord ? 'Create' : 'Save'); ?>
</div>
endWidget(); ?>
The file field submits the code to a BLOB field in mysql database.
The Controller is as follows:
public function actionCreate()
{
$model=new Estudos;
// Uncomment the following line if AJAX validation is needed
// $this->performAjaxValidation($model);
if(isset($_POST['Estudos']))
{
$model->attributes=$_POST['Estudos'];
$model->binaryfile = CUploadedFile::getInstance($model,'binaryfile'); // grava na bd no campo binaryfile
// $model->binaryfile->saveAs(Yii::app()->params['uploadPath']);
if($model->save())
$this->redirect(array('view','id'=>$model->id));
}
$this->render('create',array(
'model'=>$model,
));
}
And the Model is this one:
public function rules()
{
// NOTE: you should only define rules for those attributes that
// will receive user inputs.
return array(
array('fileName', 'length', 'max'=>100),
array('fileType', 'length', 'max'=>50),
array('binaryfile', 'safe'),
// The following rule is used by search().
// #todo Please remove those attributes that should not be searched.
array('id, fileName, fileType, binaryfile', 'safe', 'on'=>'search'),
);
}
public $uploadedFile;
// Gravar imagem na base de dados - cria blob field
public function beforeSave()
{
if ($file = CUploadedFile::getInstance($this, 'uploadedFile'))
{
$this->fileName = $file->name;
$this->fileType = $file->type;
$this->binaryfile = file_get_contents($file->tempName);
}
return parent::beforeSave();
}
The code works fine to store a file as a BLOB field, but i need to change the code to store the file in images folder and next to display links that permits to open the file (pdf file) in any browser.
To store the file in images folder i tryed saveAs() in my controller actionCreate but Yii freezes and the webpage becames blank with no error, just blank.
**Anyone can help me... I need this very very much. Many thanks in advance. **
check this link,,in this link say how do it...
http://www.yiiframework.com/wiki/2/how-to-upload-a-file-using-a-model/
Finally i've figured it by myself. The answer was rather simple, but took me 4 days to write it.
In my actionCreate() i did:
public function actionCreate()
{
$model=new Estudos;
// Uncomment the following line if AJAX validation is needed
// $this->performAjaxValidation($model);
if(isset($_POST['Estudos']))
{
$model->attributes=$_POST['Estudos'];
$model->uploadedFile=CUploadedFile::getInstance($model,'uploadedFile');
if($model->save())
$model->uploadedFile->saveAs("pdfs/".$model->uploadedFile,true);
$this->redirect(array('view','id'=>$model->id));
}
$this->render('create',array(
'model'=>$model,
));
}
**That way the saveAs() function worked like a charm and now saves my submited files in the pdfs folder.
The next step is to try and figure out how to create links for all files submitted to pdfs folder.
Maybe with a foreach() loop.
Best regards...**

Yii CMultiFileUpload select multiple files

Got The Answer
To upload multiple file in to the database for registration
have tried so many ways to make multiple file upload workable using CMultiFileUpload widget. Already, I have checked and followed below links-
http://www.yiiframework.com/forum/index.php/topic/47665-multiple-file-upload/
Yii multiple file upload
BUT still no luck!!
Error: storing the data but the files are not getting uploaded
please help
Here is my code:
In Form
<?php $this->widget('CMultiFileUpload',
array(
'model'=>$model,
'attribute' => 'documents',
'accept'=>'jpg|gif|png|doc|docx|pdf',
'denied'=>'Only doc,docx,pdf and txt are allowed',
'max'=>4,
'remove'=>'[x]',
'duplicate'=>'Already Selected',
)
);?>
Controller Code
public function actionRegistration()
{
$model=new PatientRegistration;
$this->performAjaxValidation($model);
if(isset($_POST['PatientRegistration']))
{
$model->attributes=$_POST['PatientRegistration'];
if($model->validate())
{
if(isset($_POST['PatientRegistration']))
{
if($filez=$this->uploadMultifile($model,'documents','/Images/'))
{
$model->documents=implode(",", $filez);
}
$model->attributes=$_POST['PatientRegistration'];
if($model->save())
{
// $this->render('registration',array('model'=>$model));
$this->redirect(array('/patientregistration/patientview','id'=>$model->register_id));
}
}
}
}
$this->render('registration',array('model'=>$model));
}
public function uploadMultifile($model,$attr,$path)
{
/*
* path when uploads folder is on site root.
* $path='/uploads/doc/'
*/
if($sfile=CUploadedFile::getInstances($model, $attr)){
foreach ($sfile as $i=>$file){
// $formatName=time().$i.'.'.$file->getExtensionName();
$fileName = "{$sfile[$i]}";
$formatName=time().$i.'_'.$fileName;
$file->saveAs(Yii::app()->basePath.$path.$formatName);
$ffile[$i]=$formatName;
}
return ($ffile);
}
}
Add in CActiveForm widget
'htmlOptions' => array(
'enctype' => 'multipart/form-data',
),
Hence u can use this code to upload multiple files in yiiframework
Here is the simplest Code for Multiple File Upload in Yii Framework
code
In Controller
public function actionCreate()
{
$model = new Upload;
echo Yii::app()->basePath.'/Images/';
if(isset($_POST['Upload']))
{
if($filez=$this->uploadMultifile($model,'Document','/Images/'))
{
$model->Document=implode(",", $filez);
}
$model->attributes=$_POST['Upload'];
if ($model->save())
{
$this->redirect(array('view', 'id' => $model->idUpload));
}
}
$this->render('create', array(
'model' => $model,
));
}
//Function for uploading and saving Multiple files
public function uploadMultifile ($model,$attr,$path)
{
/*
* path when uploads folder is on site root.
* $path='/uploads/doc/'
*/
if($sfile=CUploadedFile::getInstances($model, $attr)){
foreach ($sfile as $i=>$file){
// $formatName=time().$i.'.'.$file->getExtensionName();
$fileName = "{$sfile[$i]}";
$formatName=time().$i.'_'.$fileName;
$file->saveAs(Yii::app()->basePath.$path.$formatName);
$ffile[$i]=$formatName;
}
return ($ffile);
}
}
In Form
<?php $form=$this->beginWidget('CActiveForm', array(
'id'=>'upload-form',
// Please note: When you enable ajax validation, make sure the corresponding
// controller action is handling ajax validation correctly.
// There is a call to performAjaxValidation() commented in generated controller code.
// See class documentation of CActiveForm for details on this.
'enableAjaxValidation'=>false,
'htmlOptions' => array(
'enctype' => 'multipart/form-data',
),
)); ?>
<?php $this->widget('CMultiFileUpload',
array(
'model'=>$model,
'attribute' => 'Document',
'accept'=>'jpg|gif|png|doc|docx|pdf',
'denied'=>'Only doc,docx,pdf and txt are allowed',
'max'=>4,
'remove'=>'[x]',
'duplicate'=>'Already Selected',
)
);?>
That was all up is for multiple upload - that's nice, but as for multiple select you can try this yii extension
I hope that this link will help someone, because I was struggling with multiple select files for multiple upload then. Spent lot of time in Google search. Cheers

yii ajax xupload form submit is not working

Q1 : form submitting is not working.
Q2 : how to limit upload files (e.g 1 - 5 files only)
status : create a form with ajax upload xupload
My model (fadepreciation.php)
public function afterSave( ) {
$this->addImages( );
parent::afterSave( );
}
public function addImages( ) {
//If we have pending images
if( Yii::app( )->user->hasState( 'images' ) ) {
$userImages = Yii::app( )->user->getState( 'images' );
//Resolve the final path for our images
$path = Yii::app( )->getBasePath( )."/../images/uploads/{$this->id}/";
//Create the folder and give permissions if it doesnt exists
if( !is_dir( $path ) ) {
mkdir( $path );
chmod( $path, 0777 );
}
//Now lets create the corresponding models and move the files
foreach( $userImages as $image ) {
if( is_file( $image["path"] ) ) {
if( rename( $image["path"], $path.$image["filename"] ) ) {
chmod( $path.$image["filename"], 0777 );
$img = new Image( );
$img->size = $image["size"];
$img->mime = $image["mime"];
$img->name = $image["name"];
$img->source = "/images/uploads/{$this->id}/".$image["filename"];
$img->somemodel_id = $this->id;
if( !$img->save( ) ) {
//Its always good to log something
Yii::log( "Could not save Image:\n".CVarDumper::dumpAsString(
$img->getErrors( ) ), CLogger::LEVEL_ERROR );
//this exception will rollback the transaction
throw new Exception( 'Could not save Image');
}
}
} else {
//You can also throw an execption here to rollback the transaction
Yii::log( $image["path"]." is not a file", CLogger::LEVEL_WARNING );
}
}
//Clear the user's session
Yii::app( )->user->setState( 'images', null );
}
}
My view (_form.php)
<?php $form=$this->beginWidget('CActiveForm', array(
'id'=>'fa-depreciation-form',
'enableAjaxValidation'=>false,
'htmlOptions' => array('enctype' => 'multipart/form-data'),
)); ?>
<p class="note">Fields with <span class="required">*</span> are required.</p>
<?php echo $form->errorSummary($model); ?>
<!-- Other Fields... -->
<div class="row">
<?php echo $form->labelEx($model,'photos'); ?>
<?php
$this->widget( 'xupload.XUpload', array(
'url' => Yii::app( )->createUrl( "/fadepreciation/upload"),
//our XUploadForm
'model' => $photos,
//We set this for the widget to be able to target our own form
'htmlOptions' => array('id'=>'fa-depreciation-form'),
'attribute' => 'file',
'multiple' => true,
//Note that we are using a custom view for our widget
//Thats becase the default widget includes the 'form'
//which we don't want here
//'formView' => 'application.views.faDepreciation._form',
)
);
?>
</div>
<div class="row buttons">
<?php echo CHtml::submitButton($model->isNewRecord ? 'Create' : 'Save'); ?>
</div>
<?php $this->endWidget(); ?>
</div><!-- form -->
My controller (fadepreciation.php)
public function actionCreate()
{
$model=new FaDepreciation;
Yii::import( "xupload.models.XUploadForm" );
$photos = new XUploadForm;
// Uncomment the following line if AJAX validation is needed
// $this->performAjaxValidation($model);
if(isset($_POST['FaDepreciation']))
{
//Assign our safe attributes
$model->attributes=$_POST['FaDepreciation'];
//Start a transaction in case something goes wrong
$transaction = Yii::app( )->db->beginTransaction( );
try {
//Save the model to the database
if($model->save()){
$transaction->commit();
$this->redirect(array('view','id'=>$model->id));
}
} catch(Exception $e) {
$transaction->rollback( );
Yii::app( )->handleException( $e );
}
if($model->save())
$this->redirect(array('view','id'=>$model->id));
}
Yii::import( "xupload.models.XUploadForm" );
$photos = new XUploadForm;
$this->render('create',array(
'model'=>$model,
'photos'=>$photos,
));
}
public function actionUpload( ) // From xupload nothing change
What you need to do is to create a custom form.
Copy the content from xupload _form and paste it removing the begin form - end form.
Add to your widget 'formView' the reference at the custom form.
what is the issue about submission form?
yes file limit can be done. Please make sure you follow these http://www.yiiframework.com/wiki/348/xupload-workflow/
Q1: form submition is not working, because the XUpload widget generates its own form tag. so your generated HTML has a form embebed in another form, you should use formView option of the widget to point to a view that has no form tags, as described in the xupload workflow wiki
Q2: You should use maxNumberOfFiles option in the widget config
It all should look like this:
<?php
$this->widget( 'xupload.XUpload', array(
'url' => Yii::app( )->createUrl( "/fadepreciation/upload"),
//our XUploadForm
'model' => $photos,
//We set this for the widget to be able to target our own form
'htmlOptions' => array('id'=>'fa-depreciation-form'),
'attribute' => 'file',
'multiple' => true,
//Note that we are using a custom view for our widget
//Thats becase the default widget includes the 'form'
//which we don't want here
'formView' => 'application.views.faDepreciation._form',
'options' => array('maxNumberOfFiles' => 5)
)
);
?>
Just use 'showForm' parameter as follow:
<?php
$this->widget( 'xupload.XUpload', array(
...
'showForm' => false,
...
));
?>
Maybe, this option been added in next versions of xupload.
I know that it's an old post but maybe this answer will help someone to solve this issue.
I found out that it's caused by the last line in the file /xupload/views/form.php (with default settings). It looks like the if statement is somehow working opposite... in mining that for false value it's rendering the code. For example:
<?php
echo $this->showForm;
if($this->showForm) echo CHtml::endForm();
echo $this->showForm;
?>
returns:
Maybe I'm missing something but it looks weird... isn't it?

Categories