I have a Yii2 ActiveForm with two form field that accepts file input.
<?= $form->field($model, 'mainImage')->fileInput() ?>
<?= $form->field($model, 'productImage[]')->fileInput() ?>
In the controller i have:
public function actionCreate()
{
$model = new Product();
$model->supplier_id = Yii::$app->user->identity->id;
$imageArray = ['mainImage','productImage'];
$mainImageIndex = 1;
if ($model->load(Yii::$app->request->post())) {
$model->mainImage = UploadedFile::getInstance($model, 'mainImage');
$model->images = $model->singleImageUpload();
//UploadedFile::reset();
// var_dump($model->mainImage);
// exit();
$model->productImage = UploadedFile::getInstances($model, 'productImage');
$images = $model->multipleImageUpload();
$imageCount = count($images);
if ($model->validate() && $model->save(false)) {
for ($i=0; $i < $imageCount; $i++) {
$imageModel = new ProductImage();
$imageModel->product_id = $model->id;
$imageModel->image = $images[$i];
$imageModel->save();
}
return $this->redirect(['view', 'id' => $model->id]);
}
}
return $this->render('create', [
'model' => $model,
]);
}
In the Model class, I have these validations rules:
[['mainImage','productImage'], 'safe'],
[['mainImage','productImage'], 'file','skipOnEmpty' => true, 'extensions' => 'jpeg, jpg, png','checkExtensionByMimeType'=>false, 'maxFiles'=>10],
Every time i submit the form I get an error of mainImage field stating Please upload a file. There is no error for productImage
What could be the possible fix for this?
Edit
Images for mainImageand productImage are successfully uploaded though the validation error persists on for the mainImage
The problem was validation in the model class.
I had marked them as safe
[['mainImage','productImage'], 'safe'],
I commented out this validation and it worked
If you want to upload multiple files then you needed to change your view
<?= $form->field($model, 'mainImage')->fileInput() ?>
<?= $form->field($model, 'productImage[]')->fileInput(['multiple' => true, 'accept' => 'image/*']) ?>
And your rule in model says that you have been trying to upload multiple image for attributes productImage[] and mainImage. But view says that attribute mainImage used for single file so change the rule.
[['mainImage'], 'file', 'skipOnEmpty' => true, 'extensions' => 'jpeg, jpg, png'],
[['productImage'], 'file','skipOnEmpty' => true, 'extensions' => 'jpeg, jpg, png','checkExtensionByMimeType'=>false, 'maxFiles'=>10],
In controller,
$model->productImage = UploadedFile::getInstances($model, 'productImage');
$model->mainImage = UploadedFile::getInstance($model, 'mainImage');
if ($model->multipleImageUpload()) {
// file is uploaded successfully
return;
}
In your model,
public function multipleImageUpload()
{
if ($this->validate()) {
foreach ($this->imageFiles as $file) {
$file->saveAs('uploads/' . $file->baseName . '.' . $file->extension);
}
return true;
} else {
return false;
}
}
For more reference please go through this link: https://www.yiiframework.com/doc/guide/2.0/en/input-file-upload
Related
Hi im trying to upload an image but the image is not getting uploaded to the folder.
and i donĀ“t get any error message is there anyone that have a solution to this i followed the documentation on https://www.yiiframework.com/doc/guide/2.0/en/input-file-upload
Controller
public function actionUpload()
{
$model = new UploadForm();
if (Yii::$app->request->isPost) {
$model->imageFile = Uploadedfile::getInstance($model, 'imagefile');
if ($model->upload()) {
return;
}
}
return $this->render('upload', ['model' => $model]);
}
Model
public $imageFile;
public $hight;
public $width;
public function rules()
{
return [
[['imageFile'], 'file', 'skipOnEmpty' => false, 'extensions' => 'png, jpg, gif'],
];
}
public function upload()
{
if ($this->validate()) {
$path = $this->uploadPath() . $this->imageFile->namespace . '.' . $this->imageFile->extension;
$this->imageFile->saveAs($path);
$this->image = $this->imageFile->basename . '.' . $this->imageFile->extension;
return true;
} else {
return false;
}
}
public function uploadPath(){
return 'basic/web/uploads/';
}
View
<div class="col-lg-4">
<h2>Heading</h2>
<?php $form = ActiveForm::begin(['options' => ['enctype' => 'multipart/form-data']]) ?>
<?= $form->field($model, 'imageFile')->fileInput() ?>
<button>Resize</button>
<?php ActiveForm::end() ?>
</div>
I think file was not saved to basic/web/uploads folder, please do according to ex, $this->imageFile->saveAs('uploads/' ...
Also try create folder 'uploads' in web/, after this check permissions to the folder
I'm using Yii2 basic. It doesn't seems like anything's wrong, no error message displayed, but why did my image didn't upload? The rest (title, content etc) get uploaded through the form,though
This is my model's rule and related method:
public $image;
public function init(){
Yii::$app->params['uploadPath'] = Yii::$app->basePath . '/uploads/batam/';
Yii::$app->params['uploadUrl'] = Yii::$app->urlManager->baseUrl . '/uploads/batam/';
}
public function rules()
{
return [
[['title', 'content'], 'required'],
[['content'], 'string'],
[['created_at', 'updated_at','image'], 'safe'],
[['image'], 'file','extensions'=>'jpg,png,jpeg'],
[['title'], 'string', 'max' => 255],
];
}
public function getImageFile()
{
return isset($this->image) ? Yii::$app->params['uploadPath'].$this->image : null;
}
public function uploadImage() {
$image = UploadedFile::getInstance($this, 'image');
if (empty($image)) {
return false;
}
$this->image = $image->name;
return $image;
}
This is my controller
public function actionCreate()
{
$model = new News();
if ($model->load(Yii::$app->request->post()) )
{
// process uploaded image file instance
$image = $model->uploadImage();
if($model->validate())
{
if($model->save())
{
// upload only if valid uploaded file instance found
if ($image !== false)
{
$path = $model->getImageFile();
$image->saveAs($path);
}
return $this->redirect(['view', 'id'=>$model->id]);
}
}
else{echo " validation is failed";}
}
else{
return $this->render('create', [
'model' => $model,
]);
}
}
This is the form
echo $form->field($model, 'image')->widget(FileInput::classname(), [
'options' => ['accept' => 'image/*'],
'pluginOptions' => [['previewFileType' => 'any']]
]);
I had included the enctype also at the beginning of the form
<?php $form = ActiveForm::begin(['options' => ['enctype' => 'multipart/form-data']]);
At this point inside the if ($image !== false) part of the controller , the $image and $path to be saved-as contains a seemingly correct path.
This is my $path : C:\xampp\htdocs\gbia/uploads/batam/test image 1-01.jpg and my $image also contain the object (not null). This is the var_dump of my $image :
object(yii\web\UploadedFile)#179 (5) { ["name"]=> string(19) "test image 1-01.jpg" ["tempName"]=> string(24) "C:\xampp\tmp\php3199.tmp" ["type"]=> string(10) "image/jpeg" ["size"]=> int(925184) ["error"]=> int(0) }
I think something wrong with the saveAs(), but I can't figure it out. Had googled around, look on stackoverflow and tutorials but I still can't find any answer. Can someone help? Thanks
Check your model, you have declared $image as a public variable of the class, and not as a field in the database, if you want to store the data there, it will never work, as the public property that is temporary will have preference over the database column.
public $image;
So delete this field (If it is also in the db) or generate a new column name (I suggest by the name of path).
[['content', 'path'], 'string'],
Then you need to store the path, I don't see where are you doing that in the controller or class. I suggest you to add a field in the database with the "path" name and then do like this in the controller:
$path = $model->getImageFile();
$image->saveAs($path);
$model->path = $path . $image // You must store the full path plus the file name
$model->save(); // then you save the model again
Any doubt is welcome, I have example projects that I can show you if you are unable to see the light.
My view:
<?php
$form = ActiveForm::begin(['options' => ['enctype' => 'multipart/form-data']]);
?>
<?= $form->field($model, 'document_file')->fileInput()->label(Yii::t('app', 'Attachment')) ?>
<?= Html::submitButton(Yii::t('app', 'Save'), ['class' => 'btn btn-primary']) ?>
<?php ActiveForm::end(); ?>
My model:
class Documents extends \yii\db\ActiveRecord
{
public $document_file;
public function rules()
{
return [
[['document_file'], 'file', 'skipOnEmpty' => false, 'extensions' => 'png, jpg, xls'],
];
}
}
My controller:
$model = new Documents();
if($model->load(Yii::$app->request->post()) && $model->validate()) {
$model->document_file = UploadedFile::getInstance($model, 'document_file');
$model->document_file->saveAs('uploads/documents/' . $model->document_file->baseName . '.' . $model->document_file->extension);
} else {
print_r($model->getErrors());
}
return $this->render('new', compact('model'));
This code is supposed to upload file to server. But I get the error from print_r - it says
Array ( [document_file] => Array ( [0] => Upload a file. ) )
What am I doing wrong and how to upload a file to server???
File attributes (document_file in your example) could not be assigned via load(), so the value of the following expression is false:
$model->load(Yii::$app->request->post()) && $model->validate()
That is why you got the print error message. You should use UploadedFile::getInstance() to assign the document_file attribute before validate():
$model = new Documents();
if(Yii::$app->request->isPost) {
$model->document_file = UploadedFile::getInstance($model, 'document_file');
if ($model->validate()) {
$model->document_file->saveAs('uploads/documents/' . $model->document_file->baseName . '.' . $model->document_file->extension);
} else {
print_r($model->getErrors());
}
}
return $this->render('new', compact('model'));
So I've set a CRUD to upload a file to the server's root, in a folder called 'uploads'.
Now, the file is properly saved in the particular folder and the database entry appears to be alright - but the images don't display in the CRUD's 'index' and 'view' actions. Any thoughts on this one?
Create:
public function actionCreate()
{
$model = new PhotoGalleryCategories();
if ($model->load(Yii::$app->request->post())) {
$model->image = UploadedFile::getInstance($model, 'image');
if (Yii::$app->ImageUploadComponent->upload($model)) {
Yii::$app->session->setFlash('success', 'Image uploaded. Category added.');
return $this->redirect(['view', 'id' => $model->id]);
} else {
Yii::$app->session->setFlash('error', 'Proccess could not be successfully completed.');
return $this->render('create', [
'model' => $model
]);
}
} else {
return $this->render('create', [
'model' => $model,
]);
}
}
ImageUploadComponent file:
<?php
namespace app\components;
use Yii;
use yii\base\Component;
use yii\base\InvalidConfigException;
class ImageUploadComponent extends Component {
public function upload($model) {
if ($model->image) {
$imageBasePath = dirname(Yii::$app->basePath, 1) . '\uploads\\';
$imageData = 'img' . $model->image->baseName . '.' . $model->image->extension;
$time = time();
$model->image->saveAs($imageBasePath . $time . $imageData);
$model->image = $imageBasePath . $time . $imageData;
if ($model->save(false)) {
return true;
} else {
return false;
}
}
}
}
And the index file for the views:
<?php
use yii\helpers\Html;
use yii\grid\GridView;
/* #var $this yii\web\View */
/* #var $searchModel app\modules\admin\models\PhotoGalleryCategoriesSearch */
/* #var $dataProvider yii\data\ActiveDataProvider */
$this->title = 'Photo Gallery Categories';
$this->params['breadcrumbs'][] = $this->title;
?>
<div class="photo-gallery-categories-index">
<h1><?= Html::encode($this->title) ?></h1>
<?php // echo $this->render('_search', ['model' => $searchModel]); ?>
<p>
<?= Html::a('Create Photo Gallery Categories', ['create'], ['class' => 'btn btn-success']) ?>
</p>
<?= GridView::widget([
'dataProvider' => $dataProvider,
'filterModel' => $searchModel,
'columns' => [
['class' => 'yii\grid\SerialColumn'],
'name',
'image' => [
'attribute' => 'image',
'value' => 'image',
'format' => ['image', ['class' => 'col-md-6']]
],
['class' => 'yii\grid\ActionColumn'],
],
]); ?>
</div>
Edit: In the dev tools, I can see the correct source for the image. What's more, I can access it by copy-pasting the address in the browser. (the first rows are images taken from the internet through their address, they are not saved locally.)
if image upload in folder
you check below code in gridview with own path:
[
'attribute' => 'image',
'format' => 'html',
'value' => function($data) {
if (empty($data['image'])) {
$img = 'default.jpg';
} else {
$img = $data['image'];
}
if (file_exists(\Yii::$app->basePath . \Yii::$app->params['path']['product'] . $img)) {
if (file_exists(\Yii::$app->basePath . \Yii::$app->params['path']['product'] . "t-" . $img)) {
$path = \Yii::$app->params['path']['webproduct'] . "t-" . $img;
} else {
$path = \Yii::$app->params['path']['webproduct'] . $img;
}
} else {
if (file_exists(\Yii::$app->basePath . \Yii::$app->params['path']['product'] . "t-default.jpg")) {
$path = \Yii::$app->params['path']['webproduct'] . "t-default.jpg";
} else {
$path = \Yii::$app->params['path']['webproduct'] . "default.jpg";
}
}
return Html::img($path, ['width' => '100px', 'height' => '100px']);
},
],
in params.php
\Yii::$app->params['path']['webproduct']:
'product' => '/web/uploads/product/',
'webproduct' => '/uploads/product/',
notice: i use basic template.
I found this anomaly: while inspecting the image sources, I found out that Yii prepended the baseUrl to the image source, even though it displayed only the correct bit. So I manually assigned the path that goes into the database - this way the images show properly.
This is the upload function after the changes. To test it for the whole backend, I made it a component, and it works flawlessly.
public function upload($model) {
/**
* If the $model->image field is not empty, proceed to uploading.
*/
if ($model->image) {
/**
* Assign current time.
*/
$time = time();
/**
* Create the basePath for the image to be uploaded at #root/uploads.
* Create the image name.
* Create the database model.
*/
$imageBasePath = dirname(Yii::$app->basePath, 1) . '\uploads\\';
$imageData = 'img' . $model->image->baseName . '.' . $model->image->extension;
$imageDatabaseEntryPath = '../../../uploads/';
$modelImageDatabaseEntry = $imageDatabaseEntryPath . $time . $imageData;
$model->image->saveAs($imageBasePath . $time . $imageData);
$model->image = $modelImageDatabaseEntry;
/**
* If the model can be saved into the database, return true; else return false.
* Further handling will be done in the controller.
*/
if ($model->save(false)) {
return true;
} else {
return false;
}
}
}
}
My Code related is the following:
Model Rules
[['documentTypeId', 'itemId', 'name', 'document'], 'required'],
[['document'], 'file', 'skipOnEmpty' => false, 'extensions' => ['png', 'jpg', 'doc', 'pdf'], 'checkExtensionByMimeType'=>false],
Model method
public function upload($file)
{
if ($this->validate()) {
$userFolder = Yii::getAlias("#app")."/uploads/".$this->item->userId;
if(BaseFileHelper::createDirectory($userFolder) !== false) {
$fileName = uniqid(rand(), false) . '.' . $this->document->extension;
$file->saveAs($userFolder.'/' . $fileName);
$this->document = $file->name;
return true;
} else {
return false;
}
} else {
return false;
}
}
Controller
$model = new ItemDocument();
if ($model->load(Yii::$app->request->post()) && $model->validate()) {
$file = UploadedFile::getInstance($model, 'document');
if($model->upload($file) !== false) {
$model->save();
}
return $this->redirect(['view', 'id' => $model->id]);
}
return $this->render('create', [
'model' => $model,
]);
This is giving me a validation error: "Document can not be blank". If I set "Document" field as not required and submit form I get "Please upload a file."
I am uploading this through a form with some other fields.
Any ideas?
I have found the error it was the model->validate() on controller. When i do:
$model->load(Yii::$app->request->post())
File content is not loaded to the "document" field. Yii generates a hidden field which is empty. So I need first to do this:
$file = UploadedFile::getInstance($model, 'document');
So now my controller looks like this:
$model = new ItemDocument();
if ($model->load(Yii::$app->request->post())) {
$model->document = UploadedFile::getInstance($model, 'document');
if($model->validate()) {
if ($model->upload() !== false) {
$model->save();
}
return $this->redirect(['view', 'id' => $model->id]);
}
}
return $this->render('create', [
'model' => $model,
]);
And I removed the validation inside upload method on model. Hope it helps someone.