I saw many posts that community newbie is confuse in image/photo upload with random name. so I post this topic covering all useful things regarding to image/photo upload(not covering image attribute related functionality)
View : ¶
_form.php file:
..
//form options array...
'htmlOptions' => array(
'enctype' => 'multipart/form-data',
),
...
..
//Other elements
..
..
<div class="row">
<?php echo $form->labelEx($model,'image'); ?>
<?php echo CHtml::activeFileField($model, 'image'); ?> // by this we can upload image
<?php echo $form->error($model,'image'); ?>
</div>
<?php if($model->isNewRecord!='1'){ ?>
<div class="row">
<?php echo CHtml::image(Yii::app()->request->baseUrl.'/banner/'.$model->image,"image",array("width"=>200)); ?> // Image shown here if page is update page
</div>
..
..
Other elements
..
..
.. ..
Model : ¶
just add below line in rules() method in Model
array('image', 'file','types'=>'jpg, gif, png', 'allowEmpty'=>true, 'on'=>'update'), // this will allow empty field when page is update (remember here i create scenario update)
for all others rules you had to give scenario for insert and update as the rule will apply on both page( Insert and Update ) i.e:
array('title, image', 'length', 'max'=>255, 'on'=>'insert,update'),
.. .. Now comes the main part,
Controller : ¶
Create controller will upload image with random name and enter required database entry.
public function actionCreate()
{
$model=new Banner; // this is my model related to table
if(isset($_POST['Banner']))
{
$rnd = rand(0,9999); // generate random number between 0-9999
$model->attributes=$_POST['Banner'];
$uploadedFile=CUploadedFile::getInstance($model,'image');
$fileName = "{$rnd}-{$uploadedFile}"; // random number + file name
$model->image = $fileName;
if($model->save())
{
$uploadedFile->saveAs(Yii::app()->basePath.'/../banner/'.$fileName); // image will uplode to rootDirectory/banner/
$this->redirect(array('admin'));
}
}
$this->render('create',array(
'model'=>$model,
));
}
Now comes the update action,
public function actionUpdate($id)
{
$model=$this->loadModel($id);
if(isset($_POST['Banner']))
{
$_POST['Banner']['image'] = $model->image;
$model->attributes=$_POST['Banner'];
$uploadedFile=CUploadedFile::getInstance($model,'image');
if($model->save())
{
if(!empty($uploadedFile)) // check if uploaded file is set or not
{
$uploadedFile->saveAs(Yii::app()->basePath.'/../banner/'.$model->image);
}
$this->redirect(array('admin'));
}
}
$this->render('update',array(
'model'=>$model,
));
}
Above example is Upload image in specific folder and enter require entry in database. On update it will overwrite image in folder and update the data.
Random is not good
Better way is first save record and than save image, where in file name should be Primary Key of this record (PK guarantee unique). All involved in transaction and when file will not be saved than rollback.
@speedlog
@speedlog,
yes you rite, but this is just for demo purpose as upload image with random name.
setting the scenario
and dont forget to set the scenario
$model->scenario='update';
@shaan360
@shaan360, its ok if you do not add scenario on update.
you specify in model and not specify in model as $model->scenario='update' than its ok, if you specify user define scenario the you have to specify in controller.
cheers..
multipart/form-data
I could not get it to work until i added
'htmlOptions' => array( 'enctype' => 'multipart/form-data', ),
to my options array to the form (using
EBootstrapActiveForm
)I updated the article to contain that information too ...
@kmindi
yes, i think that part was missing.
@kmindi, thankx for update.
Help
Hi, if no image is submitted the page freezes. I've to do something like
if($uploadedFile != null){ $rnd = rand(0,9999); $fileName = "{$rnd}-{$uploadedFile}"; }else{ $fileName = 'default.jpg'; }
in order to prevent it. Also i've to do the same here
if($model->save()) { if($uploadedFile != null){ $uploadedFile->saveAs(Yii::app()->basePath.'/../banner/'.$fileName); } $this->redirect(array('admin')); }
This declaration inside rules
'allowEmpty' => true,'on'=>'insert,update'
should not prevent this error?
Thanks for your help
@Giacomo
Ok, so you want to store default.jpg in database and no saveAs function on empty image field.
so, just do following step:
set fileName default.jpg on empty field as
if(empty($uploadedFile)) $fileName = 'default.jpg'; // write this code below $fileName = "{$rnd}-{$uploadedFile}";
and for saveAs function use below code,
if(!empty($uploadedFile)) $uploadedFile->saveAs(Yii::app()->basePath.'/../banner/'.$fileName);
I had tested it and working fine... :D
saving 2 or 3 files
when i try your code for insert, it insert 1 record contain filename with random number and 2 record contain just random numbers?
name
instead random number is the best that use $rnd = $random = date(time());
CUploadedFile is null
hi
i use this code in ActionUpdate
$uploadedFile=CUploadedFile::getInstance($model,'image');
but $uploadedFile is null...
plz help me.
why allowEmpty on Update??????
public function rules() { // NOTE: you should only define rules for those attributes that // will receive user inputs. return array( array('social_icon', 'EImageValidator','types'=>'jpg,png,gif', 'width' => 205, 'height' => 163,'dimensionError' => 'minimum image size should be 300*300','on'=>'insert'), array('social_icon', 'EImageValidator', 'types'=>'jpg,png,gif', 'width' => 205, 'height' => 163,'dimensionError' => 'minimum image size should be 300*300','allowEmpty'=>true, 'on'=>'update'), ); }
Resizing image
hi friends. This works great!! I want to resize the image while am uploading. Is that anyway to resize image with the help of this code. help me out
resize image
> hi friends. This works great!! I want to resize the image while am uploading. Is that anyway to resize image with the help of this code.
sure you can, just use PHP function
CLICK ME
display Image
In this article, the image will be displayed while updating the file. There is any idea to display the image at the time of uploading on create.
@vijay p s
Yes, you can use any jQuery extension or core functionality for that..
Duplicate files overwritten
As mentioned already,
rand(0,9999);
can return the same number multiple times, and if the filename is also the same, the file will be overwritten. @Mariusz W. solution is one way, or just use some real random generated id like UUID4 or php uniqid()
Time instead of random
Combine php date function with rand to create unique number.
Eg: (month and day) + (rand)
Update for Yii 1.1.16
Hey Guys!
If you are using the most recent 1.1.16, there are some changes to get this working as expected.
See: https://raw.githubusercontent.com/yiisoft/yii/1.1.16/CHANGELOG
Specifically: - Bug #1257: CFileValidator is no longer unsafe by default to prevent setting arbitrary values. Instead, when no file is uploaded attribute is set to null (marcovtwout)
So, here is what I have done to get it working. Credit to Larry Ullman's book and this post:
http://www.yiiframework.com/forum/index.php/topic/63506-how-can-i-update-records-without-adding-same-image-again/page__view__findpost__p__279888
// The most important change perhaps: // In my model, the ONLY rules I have about my attribute used to store the file name are as follows: array('name', 'file', 'allowEmpty'=>false, 'types'=>'pdf', 'on'=>'insert'), array('name', 'file', 'allowEmpty'=>true, 'types'=>'pdf', 'except'=>'insert', 'safe' => false), // In my view I have this (nothing unusual) . $form=$this->beginWidget('CActiveForm', array( 'id'=>'user-form', 'enableAjaxValidation'=>false, 'htmlOptions' => array( 'enctype' => 'multipart/form-data', ) )); // And in the form I have: echo $form->fileField($model,'name'); // In the controller I have: public function actionCreate() { $model = new User; if(isset($_POST['User'])) { $model->attributes=$_POST['User']; $uploadedFile = CUploadedFile::getInstance($model, "name"); // Always a good idea to give the file a new name not likely to clash with some existing file. $fileName = "image-prefix-" . time() . "-" . $uploadedFile->getExtensionName(); $model->name = $fileName; if($model->save()) { $fullPath = Yii::app()->basePath . '/../some-folder/' . $fileName; $uploadedFile->saveAs($fullPath); $this->redirect(array('view','id'=>$model->id)); } } $this->render('create', array( 'model' => $model, )); } // Also in the controller I have public function actionUpdate($id) { $model=$this->loadModel($id); if(isset($_POST['User'])) { $model->attributes = $_POST['User']; $uploadedFile = CUploadedFile::getInstance($model, 'name'); if($model->save()) { if($uploadedFile !== null) { $fullPath = Yii::app()->basePath . '/../some-folder/' . $model->name; $uploadedFile->saveAs($fullPath); } $this->redirect(array('view','id'=>$model->id)); } } $this->render('update',array( 'model'=>$model, )); }
create action can be optionally
is there anyway to make create action optionally and update stay updating old files ??
Yii2 update
Can anybody update this functionality using yii2.0.
How to save compress large images before saving them into database, using this wiki?
Hi, I am a yii bie, I wanted to upload images, which I have done successfully, but Now I want to compress these images before they save i database. How can I achieve this using this wiki, or any modifications in the wiki ? Please Help
If you have any questions, please ask in the forum instead.
Signup or Login in order to comment.