Upload multiple files in array with yii - php

I've created a form with field in array following this link http://www.yiiframework.com/doc/guide/1.1/en/form.table
and created a file field in array like this
echo $form->fileField($m, "[$i]myfile");
But now i've no idea what i'm going to do in controller to save the file paths and filename etc. I am able to save other information but not the upload file. I've tried with this but no luck.
$imageUpload = CUploadedFile::getInstance($models[$i],'name');

Try this way, but first ensure your form type is
<?php $form=$this->beginWidget('CActiveForm', array(
'id'=>'user-form',
'htmlOptions'=>array(
'enctype' => 'multipart/form-data'
),
)); ?>
//Avatar Upload on controller start
$uploaded_file = CUploadedFile::getInstance($model,'avatar');
$main_image=null;
if($uploaded_file and $model->validate())
{
$main_image =time()."-".$model->username.".".$uploaded_file->getExtensionName();
$model->avatar=$uploaded_file;#initialize model attribute with file name
$model->avatar->saveAs(Yii::app()->basePath."/../images/profile-images/".$main_image);//this will upload selected image file
}
//Avatar Upload on controller end

This method need the browser support HTML5.
In view file:
$form=$this->beginWidget('CActiveForm', array(
'id'=>'ca-form',
'enableAjaxValidation'=>false,
'htmlOptions' => array('enctype' => 'multipart/form-data'),
));
...
echo $form->fileField($m, "myfile[]", array('multiple'=>true));
In Controller:
$imageUploads = CUploadedFile::getInstances($models,'myfile');
foreach ($imageUploads as $imageUpload) {
...// Here you can use $imageUpload->name.
}
Notice the 's' of getInstances

Related

Yii PHP file uploader overwriting on update

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));
}
}

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 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