[EXTENSION] CFile

Hi, raphi. Need time to think it all over: both checksums and comparison.

Hi, heyhoo. I’ve made some changes based on your comments.

You can verify the following commit: http://github.com/idlesign/ist-yii-cfile/raw/67c8d983d9d6779450e019eb3336b065480e46f1/CFile.php

Great! Thanks, keep up the good work!

Version 0.8 is available, introducing ‘x-sendfile’ header support to speed up file serving.

  • new: new: ‘serverHandled’ parameter in send() & download() methods allows sending even huge files with great speed

  • fix: be PHP 5.1+ compatible (proposed by heyhoo)

  • fix: permissions set incorrectly (spotted by heyhoo)

http://www.yiiframework.com/extension/cfile/

hi,

Can You put one more function into todo list - recursice dirs creation.

When you give for function stable path to images and another path with parameters to image.

Example:

C:/www/yii_project/images/ this is stable path and know I gave dynamic path - "category_id/sub_category_id/item_id/" so the function must check if there exists all three directories and if not, create them.

I think this function have to be added ;)

thanks :)

Or I can do this in another way, but I dont know how. any way, tnx for your good extension and for replays :)

I’m not certain what you’ve ment ??? Do you want autocretation in set method or what?

Describe your task step by step, please. You can put it in Russian if you’re willing to.

ok i’ll try

So I have created new item and uploaded file for example test.jpg for that item. Now I wannt to put him into directory somewhere C:/www/yii_project/images/item_category/item_sub_category/item_sub_sub_category/item_id/test.jpg

Now I have just read that I can check if this C:/www/yii_project/images/item_category/item_sub_category/item_sub_sub_category/item_id/ directory exists and if not with mkdir recursively create it.


if(!file_exists('http://localhost/yii_project/images/item_category/item_sub_category/item_sub_sub_category/item_id/'))

{

   mkdir('C:/www/yii_project/images/item_category/item_sub_category/item_sub_sub_category/item_id/', '0777', true);

}

Is there any way to do this with cfile?

I think that copy method can do this but i’m not shure.

Thanks

Yeap, you can use copy method, it should handle directory creation for you:




// Suppose you're using Item model with 'file' attribute for upload

$uploaded = Yii::app()->file->set('Item[file]');


// Let's copy newly uploaded file into your directory with file original name.

$newfile = $uploaded->copy('C:/www/yii_project/images/item_category/item_sub_category/item_sub_sub_category/item_id/'.$uploaded->basename);



:)

I just discover this :D

Thanks, good luck ;)

after set cfile object $cfile

get size of file: $cfile->getSize(false);

get wrong size format

it will return Filesystem object size formatted (eg. ‘70.4 KB’)

does not return size in bytes

Hi,

That’s true. Please try latest from https://github.com/idlesign/ist-yii-cfile/raw/36465fd7101a657fa4669997565d18a80e319473/CFile.php

Hello! Good extension. Unfortunatly I have a problem with delete() method. In project I do, we use SVN, so it creates in every folder hidden “.svn” folder. If I try to delete folder using delete() method these “.svn” folders inside the folder I try to delete are still there so at last folder is impossible to delete ('cause it is not empty). I use windows. Is it a bug or my mistake? Thanks.

Found php5 function that works (deletes .svn folders):


  public function deleteExtended($tmp_path) {

        if (!is_writeable($tmp_path) && is_dir($tmp_path)) {

            chmod($tmp_path, 0777);

        }

        $handle = opendir($tmp_path);

        while ($tmp = readdir($handle)) {

            if ($tmp != '..' && $tmp != '.' && $tmp != '') {

                if (is_writeable($tmp_path . DS . $tmp) && is_file($tmp_path . DS . $tmp)) {

                    unlink($tmp_path . DS . $tmp);

                } elseif (!is_writeable($tmp_path . DS . $tmp) && is_file($tmp_path . DS . $tmp)) {

                    chmod($tmp_path . DS . $tmp, 0666);

                    unlink($tmp_path . DS . $tmp);

                }


                if (is_writeable($tmp_path . DS . $tmp) && is_dir($tmp_path . DS . $tmp)) {

                    $this->deleteExtended($tmp_path . DS . $tmp);

                } elseif (!is_writeable($tmp_path . DS . $tmp) && is_dir($tmp_path . DS . $tmp)) {

                    chmod($tmp_path . DS . $tmp, 0777);

                    $this->deleteExtended($tmp_path . DS . $tmp);

                }

            }

        }

        closedir($handle);

        rmdir($tmp_path);

        if (!is_dir($tmp_path)) {

            return true;

        } else {

            return false;

        }

    }

I want to extend your class with it. Instead of method argument (tmp_path) I wanna use $this->_realpath in deleteExtended(), so I can access it via object. So here goes the second question.

Is it possible to create extended class from your cFile class? I need all your functionality from original class but only one new deleteExtended() method. I tried, didn’t worked out. Maybe you can help? Thanks.

Nice extension.

I wanted to do my own Component, based on your extension, because I need more advanced methods.

So I did "class CMyFile extends CFile". And then I run into problems.

I tried creating a new CMyFile instance and tried something like “file = CMyFile::set(‘files/test3.txt’)” and ended up with Call to undefined method.

Then I created a __construct method in CMyFile with “$this -> set(‘files/test3.txt’)”. Also tried parent::set and self::set. I always get returned an instance, but it’s never the CMyFile, only a new CFile.

What am I doing wrong?

Hi, GSMaN,

Try to turn on DEBUG mode and see are there any ‘Unable to delete filesystem object’ messages in the log. If so that’s permissions problem. CFile doesn’t try to change permissions on it’s own, instead you should do that explicitly.

I tried to reproduce delete fail you described on my Linux box when permissions are right, but with no success.

For answer on your second question see my next comment to edmund.

Hi, edmund,

CFile behavior you described is due to the fact that getInstance() method always returns CFile instance (line 131 - new CFile($filePath)).

But if you have PHP 5.3.0+, and really want CFile to be extendable the following should do the trick:

  1. $late_static_class = get_called_class();

  2. self::$_instances[$filePath] = new $late_static_class($filePath);

It may occur that this change will be in next CFile release with prerequisite of PHP 5.3.0+.

I did a class CMyFile of my which has an $_i property.

In the CMyFile::__construct($path) I just do $this -> _i = CMyFile::set($path).

I need a more advanced copy, so I made a new method called CMyFile::copy. I do the stuff that needs to be done before copying and then just call the CFile method: $this -> _i -> copy().

Works for me, although no proper class extension, just a workaround.

More seems like a proxy-class :)

And one more thing for this workaround and other class derivatives: inspite of C prefix (as in CFile for historical reason) Yii docs asks for E class prefix (e.g. EMyFile) for extensions.

When downloading file by calling download() method, the download is always nothing (zero file size) even though file exists and there are content in the file. After some debugs and walk through investigations, I found that the problem lies in getSize() method. When the file size hasn’t been set and false is passed as parameter, the value returned is incorrect.

The problem is fixed by adding a line to getSize() method, just before close bracket at line 635 of source code:


...

if (!isset($this->_size)){

.....

size = $this->_size; // <-- add this

}

....



Thank you. Fixed in v0.9.

Please provide an example of an entry in the file because it does not find examples.

sorry for my english