2

I am using Codeigniter's built in upload library. These are my upload settings:

$config['upload_path'] = upload_path() . 'incoming_faxes/';
$config['allowed_types'] = 'xml|pdf';
$config['file_name'] = uniqid('fax-' . time() . '-', true) . '.xml';
$this->load->library('upload', $config);

It does work. The returned data is below, however the file_name has an underscore appended:

Array
(
    [file_name] => fax-1377114300-521518bca7c5a7.65243756_.xml
    [file_type] => application/xml
    [file_path] => /var/www/vhosts/example.org/httpdocs/uploads/incoming_faxes/
    [full_path] => /var/www/vhosts/example.org/httpdocs/uploads/incoming_faxes/fax-1377114300-521518bca7c5a7.65243756_.xml
    [raw_name] => fax-1377114300-521518bca7c5a7.65243756_
    [orig_name] => fax-1377114300-521518bca7c5a7.65243756_.xml
    [client_name] => Sample.xml
    [file_ext] => .xml
    [file_size] => 84.69
    [is_image] => 
    [image_width] => 
    [image_height] => 
    [image_type] => 
    [image_size_str] => 
)

How can I remove the underscore before the file is uploaded to the server?

7

1 Answer 1

3
$fn = uniqid('fax-' . time() . '-', true);
$filename = preg_replace('/\./','_', $fn) . '.xml';

Should do it.

Test:

$parts      = explode('.', $filename);
$ext        = array_pop($parts);
$filename   = array_shift($parts);

foreach ($parts as $part)
{
    if ( 1==1)
    {
        $filename .= '.'.$part.'_';
    }
    else
    {
        $filename .= '.'.$part;
    }
}


$filename .= '.'.$ext;

echo $filename;//fax-1377117024-52152360903ae2_02709878.xml

It looks like what's happening is the _prep_filename() method in Upload.php checks the allowed_types and mimes_types against the exploded filename. The period in your filename splits off the last number before the extension (65243756 in your example filename) into the parts array. It then checks this value against allowed_types and mimes_types. Unable to find the number in allowed_types nor in mimes_types, it appends the underscore.

It's a strange issue. See here for more info: https://github.com/EllisLab/CodeIgniter/issues/1380

Breaking it down:

// system/core/libraries/Upload.php
// line 984
protected function _prep_filename($filename)
{
    if (strpos($filename, '.') === FALSE OR $this->allowed_types == '*')
    {
        return $filename;
    }

    $parts      = explode('.', $filename);
    $ext        = array_pop($parts);
    $filename   = array_shift($parts);

    foreach ($parts as $part)
    {
        if ( ! in_array(strtolower($part), $this->allowed_types) OR $this->mimes_types(strtolower($part)) === FALSE)
        {
            $filename .= '.'.$part.'_';
        }
        else
        {
            $filename .= '.'.$part;
        }
    }

    $filename .= '.'.$ext;

    return $filename;
}

Given file name fax-1377114300-521518bca7c5a7.65243756.xml, this is what happens.

$parts     = explode('.', $filename);

this breaks up $filename into an array containing 3 values:

print_r($parts); //Array ( [0] => fax-1377119574-52152d561f4694 [1] => 21065888 [2] => xml )

next line...

$ext       = array_pop($parts);

pops the $parts array:

print_r($parts); //Array ( [0] => fax-1377119706-52152dda0205e5 [1] => 29551151 )

next line...

$filename   = array_shift($parts);

shifts the array:

print_r($parts); //Array ( [0] => 39795691 )

so that now $parts contains only one item: 39795691.

Now it runs

foreach ($parts as $part)
{
    if ( ! in_array(strtolower($part), $this->allowed_types) OR $this->mimes_types(strtolower($part)) === FALSE)
    {
        $filename .= '.'.$part.'_';
    }
    else
    {
        $filename .= '.'.$part;
    }
}

which checks to see if any of the values in $parts (remember, in this case we only have the one item: 39795691) is in the allowed_types or mime_types arrays. Since it's a number and isn't in either of those arrays, it concatenates the part into the $filename variable and appends the underscore.

Sign up to request clarification or add additional context in comments.

4 Comments

I want to do this BEFORE it is uploaded. If I echo $config['file_name'] there is no period OR underscore at the end. And with your explanation, you are saying it splits off the last number, do you mean it literally removes the last number and replaces it with a period?
Well, you set $config before you upload. So set $filename before config and set $config['file_name'] = $filename;
No it doesn't remove the last number and replace it with underscore... I updated the answer to hopefully clarify what's going on.
Wow, great explanation. Thank you. After I read it I was able to just do a much simpler solution. I remove true from uniqid which disables more_entropy and it stopped adding the underscore because of that. Thanks again!

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.