Giter Site home page Giter Site logo

yii2-upload-behavior's Introduction

Upload behavior for Yii 2

This behavior automatically uploads file and fills the specified attribute with a value of the name of the uploaded file. This code is inspired by, but not derived from, https://github.com/yii-dream-team/yii2-upload-behavior.

Latest Version Software License Build Status Quality Score

Installation

The preferred way to install this extension via composer.

Either run

php composer.phar require --prefer-dist mohorev/yii2-upload-behavior "*"

or add this code line to the require section of your composer.json file:

"mohorev/yii2-upload-behavior": "*"

Usage

Upload file

Attach the behavior in your model:

class Document extends ActiveRecord
{
    /**
     * @inheritdoc
     */
    public function rules()
    {
        return [
            ['file', 'file', 'extensions' => 'doc, docx, pdf', 'on' => ['insert', 'update']],
        ];
    }

    /**
     * @return \yii\db\ActiveQuery
     */
    public function getCategory()
    {
        return $this->hasOne(Category::class, [ 'id' => 'id_category' ]);
    }

    /**
     * @inheritdoc
     */
    function behaviors()
    {
        return [
            [
                'class' => UploadBehavior::class,
                'attribute' => 'file',
                'scenarios' => ['insert', 'update'],
                'path' => '@webroot/upload/docs/{category.id}',
                'url' => '@web/upload/docs/{category.id}',
            ],
        ];
    }
}

Set model scenario in controller action:

class Controller extends Controller
{
    public function actionCreate($id)
    {
        $model = $this->findModel($id);
        $model->setScenario('insert'); // Note! Set upload behavior scenario.
        
        ...
        ...
    }
}

Example view file:

<?php $form = ActiveForm::begin(['options' => ['enctype' => 'multipart/form-data']]); ?>
    <?= $form->field($model, 'image')->fileInput() ?>
    <div class="form-group">
        <?= Html::submitButton('Submit', ['class' => 'btn btn-primary']) ?>
    </div>
<?php ActiveForm::end(); ?>

Upload image and create thumbnails

Thumbnails processing requires yiisoft/yii2-imagine to be installed.

Attach the behavior in your model:

class User extends ActiveRecord
{
    /**
     * @inheritdoc
     */
    public function rules()
    {
        return [
            ['image', 'image', 'extensions' => 'jpg, jpeg, gif, png', 'on' => ['insert', 'update']],
        ];
    }

    /**
     * @inheritdoc
     */
    public function behaviors()
    {
        return [
            [
                'class' => \mohorev\file\UploadImageBehavior::class,
                'attribute' => 'image',
                'scenarios' => ['insert', 'update'],
                'placeholder' => '@app/modules/user/assets/images/userpic.jpg',
                'path' => '@webroot/upload/user/{id}',
                'url' => '@web/upload/user/{id}',
                'thumbs' => [
                    'thumb' => ['width' => 400, 'quality' => 90],
                    'preview' => ['width' => 200, 'height' => 200],
                    'news_thumb' => ['width' => 200, 'height' => 200, 'bg_color' => '000'],
                ],
            ],
        ];
    }
}

Example view file:

<?php $form = ActiveForm::begin(['options' => ['enctype' => 'multipart/form-data']]); ?>
    <div class="form-group">
        <div class="row">
            <div class="col-lg-6">
                <!-- Original image -->
                <?= Html::img($model->getUploadUrl('image'), ['class' => 'img-thumbnail']) ?>
            </div>
            <div class="col-lg-4">
                <!-- Thumb 1 (thumb profile) -->
                <?= Html::img($model->getThumbUploadUrl('image'), ['class' => 'img-thumbnail']) ?>
            </div>
            <div class="col-lg-2">
                <!-- Thumb 2 (preview profile) -->
                <?= Html::img($model->getThumbUploadUrl('image', 'preview'), ['class' => 'img-thumbnail']) ?>
            </div>
        </div>
    </div>
    <?= $form->field($model, 'image')->fileInput(['accept' => 'image/*']) ?>
    <div class="form-group">
        <?= Html::submitButton('Submit', ['class' => 'btn btn-primary']) ?>
    </div>
<?php ActiveForm::end(); ?>

Behavior Options

  • attribute - The attribute which holds the attachment
  • scenarios - The scenarios in which the behavior will be triggered
  • instanceByName - Getting file instance by name, If you use UploadBehavior in RESTfull application and you do not need a prefix of the model name, set the property instanceByName = false, default value is false
  • path - the base path or path alias to the directory in which to save files.
  • url - the base URL or path alias for this file
  • generateNewName - Set true or anonymous function takes the old filename and returns a new name, default value is true
  • unlinkOnSave - If true current attribute file will be deleted, default value is true
  • unlinkOnDelete - If true current attribute file will be deleted after model deletion.
  • deleteOriginalFile - Only for UploadImageBehavior. If true original image file will be deleted after thumbs generating, default value is false.

Attention!

It is prefered to use immutable placeholder in url and path options, other words try don't use related attributes that can be changed. There's bad practice. For example:

class Track extends ActiveRecord
{
    public function getArtist()
    {
        return $this->hasOne(Artist::class, [ 'id' => 'id_artist' ]);
    }

    public function behaviors()
    {
        return [
            [
                'class' => UploadBehavior::class,
                'attribute' => 'image',
                'scenarios' => ['default'],
                'path' => '@webroot/uploads/{artist.slug}',
                'url' => '@web/uploads/{artist.slug}',
            ],
        ];
    }
}

If related model attribute slug will change, you must change folders' names too, otherwise behavior will works not correctly.

yii2-upload-behavior's People

Contributors

aleksandrchernyavenko avatar chuprik avatar cronfy avatar demogorgorn avatar elisdn avatar jazzman avatar microinginer avatar mohorev avatar mydesign avatar niksamokhvalov avatar rinu avatar ufocoder avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

yii2-upload-behavior's Issues

Class 'backend\models\UploadImageBehavior' not found

Добрый день. Установил через композер расширение.

Модель Post

public function behaviors()
{
return [
'image' => [
'class' => UploadImageBehavior::className(),
'attribute' => 'image',
'scenarios' => ['insert', 'update'],
'path' => '@webroot/uploads/images/{id}',
'url' => '@web/uploads/images/{id}',
'thumbs' => [
'thumb' => ['width' => 400, 'quality' => 90],
'preview' => ['width' => 200, 'height' => 200],
],
],
];
}

Ругается "Class 'backend\models\UploadImageBehavior' not found"

И еще вопрос, в мануале у вас

getUploadUrl('image'), ['class' => 'img-thumbnail']) ?>
        <div class="col-lg-4">
            <!-- Thumb 1 (thumb profile) -->
            <?= Html::img($model->getThumbUploadUrl('image'), ['class' => 'img-thumbnail']) ?>
        </div>
        <div class="col-lg-2">
            <!-- Thumb 2 (preview profile) -->
            <?= Html::img($model->getThumbUploadUrl('image', 'preview'), ['class' => 'img-thumbnail']) ?>
        </div>
getUploadUrl('image'), ['class' => 'img-thumbnail']) ?> можете примерно подсказать что из себя представляет данный метод?

Я так понимаю, это выдергивание пути из базы. Но, как это будет выглядеть если там еще пусто (при создании)

How resize image on upload

There is possibility to set up size of thumbnail images.
But how could I define size of main image to save on upload process?

gd-png

imagepng(): gd-png: fatal libpng error: zlib failed to initialize compressor -- stream error

Any fixes?

MIT violation

Чувак, если клонируешь чужие компоненты, распространяемые под MIT лицензией - будь добр, сохраняй авторство.

Model and image deleting order

Hi.
Behavior deletes image in beforeDelete() method now. But if model has foreign key constraints and related data in other tables, behavior unlinks images, but model won't be deleted. So we have IntegrityException and model without image.
I think it would be better to move code:

$attribute = $this->attribute;
if ($this->unlinkOnDelete && $attribute) {
    $this->delete($attribute);
}

from beforeDelete() into afterDelete() method to be sure that we just do not need this image.

#31

Проблема с присвоением значения

При использовании поведения была обнаружена проблема с присвоением значения атрибуту в обход поведения. Не знаю как сформулировать, проще показать.

$model->setAttribute('image_filename', '6235827635.png');

В свойстве image_filename будет NULL. Потому что в строке 149 файла UploadBehavior.php происходит unset() свойства.
Хотя в строке 150 закомментировано правильное решение.
Поведение не должно ломать общую логику работы с свойствами модели)

On model delete extension doesn't remove images folder

When extension saves image it creates a folder for that.
But on model delete it doesn't remove the folder, just image & thumbs.
I think it should remove that empty folder as well. Otherwise there will be thousands of garbage folders.

How to integrate with dynamic form

Hello, i want to integrate with dynamic_form

This is use multipleModel in save schema, I use this behavior in PortfolioImage like :

public function actionCreate(){
        $model = new Portfolio();
        $modelPortfolioImages = [new PortfolioImage];
        ..............
}

but why throw :

Setting unknown property: mongosoft\file\UploadImageBehavior::0


//highlight in this line
$modelPortfolioImages = [new PortfolioImage];

Sorry if the question does not relate, I just want to ask if could uploadBehavior when the initialisation model created with the array as above ?

Conflict because of yii2-imagine version

In my project there is yiisoft/yii2-imagine: "^2.1" requirement. It uses features from 2.1 version and can't work with 2.0.

But mohorev/yii2-upload-behavior requires "yiisoft/yii2-imagine": "~2.0.0".

So, I can't install both: composer reports conflict.

Is there any way to drop yiisoft/yii2-imagine dependency for those who does not use thumbnails?

Alternative saving (deploy to CDN, image manipulation) by passing a closure

When files are uploaded, they are not always saved to local file system. For example, one might need to deploy them to some other service using an API. Or do some image-processing.

It would be of great help, if your extension supported passing a closure for that purpose, for example:

'doSave' => function ($behavior) {
     ...//code to upload the file to CDN
}

Thank you!

The behavior does not delee generated folders

First of all thanks for sharing this nice work.

I'm using it in my project and it seems to work quite well,
my only problem is then when I upload the file the behavior create the folder if this one does not exit: this is correct for me, but when I delete the model the behavior remove files and keep folder empty.

            'path' => '@webroot/uploads/{id}',
            'url' => '@web/uploads/{id}',

I mean the after deleted model I still have the "id" generated folder

I guess this should be fine in some situations, but It would be nice to have the possibility (setting an attribute) to delete the folder when this is left empty.

Thanks in advance for any contribution

Несколько моделей с одним поведением

Добрый день!
Подскажите пожалуйста, как можно использовать поведение, если на странице размещено несколько экземпляров одной модели с прикрепленным поведением.
Т.е. например, модель Item c полем image. На странице нужно разместить несколько таких моделей для редактирования (в оригинале - произвольное кол-во) с загрузкой картинок. Вопрос в том, как правильно назначить name для input картинок и как указать атрибут для поведения?

Option saveType, related attributes in placeholded

I offer to create behavior option called saveType, that define how model attribute will be saved, and rewrite behavior according this new feature

This option saveType could have value something like that:

  • file - you upload file, and attribute will be save as filename - file.doc, this value is default
  • path - you upload file and attribute will be save as filename with path - /path/file.doc

Path value could resolve future problems with related attribute values in placeholders:

For example:

    public function getArtist()
    {
        return $this->hasOne(Artist::className(), [ 'id' => 'id_artist' ]);
    }

    public function behaviors()
    {
        return [
            [
                'class'     => UploadBehavior::className(),
                'attribute' => 'image',
                'scenarios' => [ 'default' ],
                'path'      => '@webroot/uploads/{artist.slug}/',
                'url'       => '@web/uploads/{artist.slug}/',
            ],
        ];
    }

And if $model->artist->slug will be changed, then $model->getUploadUrl('image') will resolve with wrong value

Поведение не работает с табличным вводом?

Здравствуйте. Появилась необходимость обработки нескольких моделей одного вида в одной форме. Другими словами использовать табличный ввод.
В моем случае для каждой модели есть строковые поле загрузки файла вида:
$form->field($model, "[$model->id]filename")->fileInput();

Но поведение не обрабатывает такой кейс.
Аналогичная проблема упоминалась здесь
Решение проблемы предложил maxxi165
"В общем, проблема в следующем. В beforeValidate() поведения файл для модели загружается строкой...
в случае, когда на странице несколько экземпляров модели с файлами, нужно загружать так:
$this->file = UploadedFile::getInstance($model, "[$index]" . $this->attribute);"

Оно действительно работает, если влезть в код библиотеки. Была мысль переопределить beforeValidate(), но я не могу этого сделать т.к. в нем идет обращение к приватному свойству $this->_file

Подскажите как можно решить данную проблему?

finfo_file(/private/var/tmp/phpQFyfZ5): failed to open stream: No such file or directory

I am using this config:

[
           'class' => UploadImageBehavior::class,
           'attribute' => 'recipe_image',
           'scenarios' => ['default'],
           //'placeholder' => '@app/modules/user/assets/images/userpic.jpg',
           'path' => '@webroot/media/recipe/{id}',
           'url' => '@web/media/recipe/{id}',
           'unlinkOnDelete' => true,
           'thumbs' => [
               'thumb' => ['width' => 400, 'quality' => 90],
               'preview' => ['width' => 200, 'height' => 200],
               'news_thumb' => ['width' => 200, 'height' => 200, 'bg_color' => '000'],
           ],
],

What could be the reason for this error, I googled this issue and found the solution which suggests saving file before model.

Allow Deletion of File

There is no way to explicitly remove a file. If a file is not submitted, we protect the attribute so it doesn't change. If a file is submitted, we optionally delete the old file and upload the new one.

I propose the following enhancement:

If the attribute is submitted as the string "deleted", then we will delete the uploaded file. This will still allow upload of any file, including files named "deleted", since those will automatically be transformed into an instance of UploadedFile in the beforeValidate handler.

Upload multi field in one form

I have form with have 5 file upload

function behaviors(){
    return [
        'image' => [
            'class' => UploadBehavior::className(),
            'attribute' => 'image',
            'scenarios' => ['insert', 'update'],
            'path' => '@webroot/upload/docs/{category.id}',
            'url' => '@web/upload/docs/{category.id}',
        ],
        'image_2' => [
            'class' => UploadBehavior::className(),
            'attribute' => 'image_2',
            'scenarios' => ['insert', 'update'],
            'path' => '@webroot/upload/docs/{category.id}',
            'url' => '@web/upload/docs/{category.id}',
        ],
        'image_3' => [
            'class' => UploadBehavior::className(),
            'attribute' => 'image_3',
            'scenarios' => ['insert', 'update'],
            'path' => '@webroot/upload/docs/{category.id}',
            'url' => '@web/upload/docs/{category.id}',
        ],
        'image_4' => [
            'class' => UploadBehavior::className(),
            'attribute' => 'image_4',
            'scenarios' => ['insert', 'update'],
            'path' => '@webroot/upload/docs/{category.id}',
            'url' => '@web/upload/docs/{category.id}',
        ],
        'image_5' => [
            'class' => UploadBehavior::className(),
            'attribute' => 'image_5',
            'scenarios' => ['insert', 'update'],
            'path' => '@webroot/upload/docs/{category.id}',
            'url' => '@web/upload/docs/{category.id}',
        ],
    ];
}

public function rules(){
    return [
        ...
        [['image','image_2','image_3','image_4','image_5'], 'safe'],
        [['image','image_2','image_3','image_4','image_5'], 'image', 'extensions' => 'jpg, jpeg, gif, png', 'on' => ['insert', 'update']],
    ];
}

with view :

<?= $form->field($model, 'image')->fileInput() ?>
<?= $form->field($model, 'image_2')->fileInput() ?>
<?= $form->field($model, 'image_3')->fileInput() ?>
<?= $form->field($model, 'image_4')->fileInput() ?>
<?= $form->field($model, 'image_4')->fileInput() ?>

But when i save data, all image is first image. Must chose image for first image > save > edit data again > and chose second image > save > edit data > and chose third image .....

It's limitation, or i had same mistake ?

Extension doesn't work

I configured it like in documentation, but it doesn't work. No errors. Image just not saving neither in model nor on disk.
Model

    public function rules()
    {
        return [
            ['image', 'image', 'extensions' => 'jpg, jpeg, gif, png', 'on' => ['insert', 'update']],
        ];
    }

    public function behaviors()
    {
        return [
            TimestampBehavior::className(),
            [
                'class' => \mongosoft\file\UploadImageBehavior::className(),
                'attribute' => 'image',
                'scenarios' => ['insert', 'update'],
                'placeholder' => '@webroot/images/no_image.png',
                'path' => '@webroot/uploads/images/article/article_{id}',
                'url' => '@web/uploads/images/article/article_{id}',
                'thumbs' => [
                    'thumb' => ['width' => 150, 'height' => 150],
                ],
            ],
        ];
    }

View

    <?php
    $form = ActiveForm::begin([
        'enableAjaxValidation' => true,
        'validateOnBlur' => false,
        'validateOnChange' => false,
        'options' => ['enctype' => 'multipart/form-data'],
    ]); ?>
 <?= $form->field($model, 'image')->fileInput(['accept' => 'image/*']) ?>

Controller

    public function actionCreate()
    {
        $model = new Article();

        if (Yii::$app->request->isAjax && $model->load(Yii::$app->request->post())) {
            Yii::$app->response->format = Response::FORMAT_JSON;
            return ActiveForm::validate($model);
        } elseif ($model->load(Yii::$app->request->post()) && $model->save()) {

            Yii::$app->session->setFlash(
                'success', Yii::t('app', 'Article successfully created.')
            );
            return $this->redirect(['view', 'id' => $model->id]);
        } 

            return $this->render('create', [
                'model' => $model,
            ]);
    }

Anything else?

Allow background alpha in config

In thumbs config I should be able to override yii\imagine\Image::$thumbnailBackgroundAlpha

This would need to be set to 0 to preserve an image's transparent background.

png compression level error

When uploading PNG-image and expecting thumbnail to be created:

Imagine\Exception\InvalidArgumentException
png_compression_level option should be an integer from 0 to 9

How to use with separate FormModel?

I don`t clearly understand, what we shold do, if there are separate FormModel, with the help of which the main ActiveRecord model is manipulated. Can i see some example? Thanks

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.