Go Back   CodingForums.com > :: Server side development > PHP > Post a PHP snippet

Before you post, read our: Rules & Posting Guidelines

Reply
 
Thread Tools Rating: Thread Rating: 2 votes, 3.00 average.
Enjoy an ad free experience by logging in. Not a member yet? Register.
Old 02-12-2006, 12:02 AM   PM User | #1
fci
Senior Coder

 
Join Date: Aug 2004
Location: Twin Cities
Posts: 1,345
Thanks: 0
Thanked 0 Times in 0 Posts
fci is an unknown quantity at this point
file upload class

drive crashed on a forum I run, gave me the opportunity to re-write some old slop code.

The class:
PHP Code:
<?php

define
('FILE_UPLOAD_ERR_PATH'10);
define('FILE_UPLOAD_ERR_SIZE'11);
define('FILE_UPLOAD_ERR_TYPE'12);
define('FILE_UPLOAD_ERR_INVALID'13);

class 
File_upload {

    var 
$path;

    var 
$_allowed;
    var 
$_max_size;

    var 
$_is_error//(bool)
    
var $_errno;

    function 
File_upload() {
        
$this->_allowed_mime = array();
        
$this->_allowed_ext  = array();
        
$this->_is_error     false;
        
$this->_errno        0;
        
$this->path          '';
        
$this->_max_size     100000;
    }

    function 
allow($type) {
    
        switch (
$type) {
            case 
'images' :
                
$this->_allowed['image/gif']  = array('gif');
                
$this->_allowed['image/png']  = array('png');
                
$this->_allowed['image/jpeg'] = array('jpg''jpeg');
                
$this->_allowed['image/pjpeg'] = $this->_allowed['image/jpeg'];
                break;
        }
    }

    function 
add_allowed($mime$ext) {
        
$this->_allowed[$mime] = $ext;
    }
    function 
get_extensions() {
        
$all_ext = array();
        foreach (
$this->_allowed as $exts)
            foreach(
$exts as $ext)
                
$all_ext[] = $ext;
        return 
$all_ext;
    }

    function 
upload($file) {
        
extract($file);
        
// $type, $name, $tmp_name, $size, $error

        
if (UPLOAD_ERR_OK!=$error) {
            
$this->_is_error true;
            
$this->_errno    $error;
            return 
false;
        }
        
$path $this->get_path();
        if (!
is_dir($path) || $path=='') {
            
$this->_is_error true;
            
$this->_errno    FILE_UPLOAD_ERR_PATH;
            return 
false;
        }
        if (
$size>$this->get_max_size()) {
            
$this->_is_error true;
            
$this->_errno    FILE_UPLOAD_ERR_SIZE;
            return 
false;
        }

        if (!isset(
$this->_allowed[$type])) {
            
$this->_is_error true;
            
$this->_errno    FILE_UPLOAD_ERR_TYPE;
            return 
false;
        }
        
        
$ext strtolower(File_upload::file_extension($name));
        if (!
$ext || !in_array($ext$this->_allowed[$type])) {
            
$this->_is_error true;
            
$this->_errno    FILE_UPLOAD_ERR_TYPE;
            return 
false;
        }

        if (!
is_uploaded_file($tmp_name)) {
            
$this->_is_error true;
            
$this->_errno    FILE_UPLOAD_ERR_INVALID;
            return 
false;
        }


        
// cleanup file name to be cool
        
$name preg_replace('/[^a-zA-Z0-9. ]+/','_',$name); 
        
        
// auto rename
        
$name File_upload::unique_filename($path$name);
        
        
move_uploaded_file($tmp_name$path.$name);

        
// extra paranoid to prevent any execution ever
        
chmod($path.$name0644);

        return 
$name;
    }

    function 
upload_multiple($files) {
        
$total count($files['name']);
        
$filenames = array();
        for (
$x=0$x<$total$x++) {
            
$filenames[] = $this->upload( array(
                
'name' => $files['name'][$x],
                
'type' => $files['type'][$x],
                
'tmp_name' => $files['tmp_name'][$x],
                
'error'    => $files['error'][$x],
                
'size'     => $files['size'][$x],
            ));
        }
        return 
$filenames;
    }

    function 
file_extension($file) {
        
$ext array_pop(explode("."$file));
        if (
$ext==$file)
            return 
false;
        return 
$ext;
    }

    function 
set_max_size($size=0) { $this->_max_size $size; }
    function 
get_max_size()        { return $this->_max_size; }

    function 
get_error() {
        switch (
$this->_errno) {
            case 
UPLOAD_ERR_INI_SIZE :
                return 
'The uploaded file exceeds the upload_max_filesize directive in php.ini.';
            case 
UPLOAD_ERR_FORM_SIZE :
                return 
' The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form.';
            case 
UPLOAD_ERR_PARTIAL :
                return 
'The uploaded file was only partially uploaded.';
            case 
UPLOAD_ERR_NO_FILE :
                return 
'No file was uploaded.';
            case 
UPLOAD_ERR_NO_TMP_DIR :
                return 
'Missing a temporary folder.';
            case 
UPLOAD_ERR_CANT_WRITE :
                return 
'Failed to write file to disk.';
            case 
FILE_UPLOAD_ERR_PATH :
                return 
'Upload path is not a directory.';
            case 
FILE_UPLOAD_ERR_SIZE :
                return 
'The uploaded file exceeds the max file size.';
            case 
FILE_UPLOAD_ERR_TYPE:
                return 
'The uploaded file type is invalid.';
            case 
FILE_UPLOAD_ERR_INVALID:
                return 
'The file is not an actual uploaded file.';
        }
        return 
'Unknown error ('.intval($this->errno).')';
    }

    function 
is_error()      { return $this->_is_error; }
    function 
set_path($path) { $this->path $path; }
    function 
get_path()      { return $this->path; }
    
    function 
unique_filename($path$name) {

        if (!
file_exists($path.$name))
            return 
$name;

        return 
File_upload::unique_filename($pathmd5(time().rand()).$name);
    }

}

?>
example code usage for actually uploading the file:
PHP Code:
<?php

        $is_upload 
$_GET['upload'] && !empty($_FILES);
        if (
$is_upload) {
            
$upload = new File_upload();
            
$upload->allow('images');
            
$upload->set_path('/home/user/public_html/uploads/');
            
$upload->set_max_size(500000);
            
$filename $upload->upload($_FILES['file']);
            
$error false;
            if (
$upload->is_error()) {
                
$error true;
                
$errstr$upload->get_error();
            }
        }

?>
example code needed for uploading a single file:
PHP Code:
        <h1>Image Upload</h1><br />
        <form enctype="multipart/form-data" method="POST" action="?mode=upload&upload=1">
            <input type="hidden" name="MAX_FILE_SIZE" value="500000" />
            <table width="300" cellpadding="3" cellspacing="0" border="0">
                <tr>
                    <td><input name="file" type="file" size="50"></td>
                </tr>
                <tr>
                    <td align="right">
                        <input type="submit" value="Upload Image">
                    </td>
                </tr>
            </table>
        </form>
        <p style="font-size:8pt;">
        Allowed file extensions are JPG, JPEG PNG, GIF and max file size is 500kb
        </p>
        <?php 
        
if ($is_upload && $error) {
            print 
'<strong>Error: '.$errstr.'</strong><br />';
        } else if (
$is_upload) {
            
$image _URL_.'uploads/'.$filename
            print 
'<input type="text" size="'.strlen($image).'" value="[img]'.$image.'[/img]"><br />';
            print 
'<img src="'.$image.'">';
        }
?>
it will need to be modified to allow other file types.. so hopefully someone can reply to this thread for whatever their need is and I can update it ... it is currently used for uploading images.

Multiple files by request:
I had to revise the main class to accept multiple files (upload_multiple method). copy and paste the updated class.

example usage php for doing the actual upload:
PHP Code:
<?php
        $is_upload 
$_GET['upload'] && !empty($_FILES);
        
$max_size 250000
        
$max_uploads  5;
        if (
$is_upload) {
            if (
count($_FILES['file']['name'])<=$max_uploads) {
                
$upload = new File_upload();
                
$upload->allow('images');
                
$upload->set_path('/home/ecnet/public_html/uploads/');
                
$upload->set_max_size($max_size);

                
$files $upload->upload_multiple($_FILES['file']);
                
$error false;
                if (
$upload->is_error()) {
                    
$error true
                    
$errstr$upload->get_error();
                }       
            } else {
                
$error true
                
$errstr'Trying to upload to many files';
            }   
        }       
?>

example usage as far as HTML etc
PHP Code:
        <h1>Image Upload</h1><br />
        <script type="text/javascript"><!--
        var gFiles = 0;
        function addFile() {
            var tr = document.createElement('tr');
            tr.setAttribute('id', 'file-' + gFiles);
            var td = document.createElement('td');
            td.innerHTML = '<input type="file" size="30" name="file[]"><span onclick="removeFile(\'file-' + gFiles + '\')" style="cursor:pointer;">Remove</span>';
            tr.appendChild(td);
            document.getElementById('files-root').appendChild(tr);
            gFiles++;
        }
        function removeFile(aId) {
            var obj = document.getElementById(aId);
            obj.parentNode.removeChild(obj);
        }

        --></script>
        <form enctype="multipart/form-data" method="POST" action="?mode=misc&action=upload&upload=1">
        <span onclick="addFile()" style="cursor:pointer;cursor:hand;">Add</span> 
        <input type="hidden" name="MAX_FILE_SIZE" value="<?php echo $max_size?>" />
            <table><tbody id="files-root">
            <tr><td><input type="file" name="file[]" size="30"></td></tr>
            </table>
            <input type="submit" value="Upload Image">
        </form> 
        <p style="font-size:8pt;">
    allowed extensions are: <strong>JPG, JPEG PNG, GIF</strong>; max size per file: <strong>250kb</strong>; max number of files per upload <strong><?php echo $max_uploads?>
        </p>    
        <?php 
        
if ($is_upload && $error) {
            print 
'<strong>Error: '.$errstr.'</strong><br />';
        } else if (
$is_upload) {
            foreach (
$files as $file) {
                
$image _URL_.'uploads/'.$file;
                print 
'<input type="text" size="'.strlen($image).'" value="[img]'.$image.'[/img]"><br />';
                print 
'<img src="'.$image.'">';
            }           
        }       


?>
js code for file add/remove located here:
http://www.codingforums.com/showthread.php?t=65390

edit:
Thu Feb 16 18:11:12 CST 2006 - bug fix on images, missing image/pjpeg mime

Last edited by fci; 02-17-2006 at 12:04 AM..
fci is offline   Reply With Quote
Old 02-13-2006, 09:12 AM   PM User | #2
esthera
Senior Coder

 
Join Date: May 2004
Posts: 1,430
Thanks: 14
Thanked 0 Times in 0 Posts
esthera can only hope to improve
can this be used to upload multiple files?
esthera is offline   Reply With Quote
Old 02-13-2006, 01:06 PM   PM User | #3
fci
Senior Coder

 
Join Date: Aug 2004
Location: Twin Cities
Posts: 1,345
Thanks: 0
Thanked 0 Times in 0 Posts
fci is an unknown quantity at this point
Quote:
Originally Posted by esthera
can this be used to upload multiple files?
yes, it could, I'll write up an example later today when I have time
fci is offline   Reply With Quote
Old 02-14-2006, 04:57 AM   PM User | #4
fci
Senior Coder

 
Join Date: Aug 2004
Location: Twin Cities
Posts: 1,345
Thanks: 0
Thanked 0 Times in 0 Posts
fci is an unknown quantity at this point
ok, refer to top post

to do(or to not do, depending on how it goes ):
- make sure filename is completely unique by checking if file_exists again and again until it passes
- better way to set allowed file types and a get method to return them as an array.
- use is_uploaded_file http://us3.php.net/manual/en/functio...oaded-file.php
edit, i just felt like doing it tonight (updated top post again)

Last edited by fci; 02-14-2006 at 05:30 AM..
fci is offline   Reply With Quote
Old 05-05-2006, 07:24 PM   PM User | #5
fci
Senior Coder

 
Join Date: Aug 2004
Location: Twin Cities
Posts: 1,345
Thanks: 0
Thanked 0 Times in 0 Posts
fci is an unknown quantity at this point
some minor updates.. passes E_ALL now.. and E_STRICT eventually.
PHP Code:
<?php

if (!defined('UPLOAD_ERR_OK'))
    
define('UPLOAD_ERR_OK'0);

if (!
defined('UPLOAD_ERR_INI_SIZE'))
    
define('UPLOAD_ERR_INI_SIZE'1);

if (!
defined('UPLOAD_ERR_FORM_SIZE'))
    
define('UPLOAD_ERR_FORM_SIZE'2);

if (!
defined('UPLOAD_ERR_PARTIAL'))
    
define('UPLOAD_ERR_PARTIAL'3);

if (!
defined('UPLOAD_ERR_NO_FILE'))
    
define('UPLOAD_ERR_NO_FILE'4);

if (!
defined('UPLOAD_ERR_NO_TMP_DIR'))
    
define('UPLOAD_ERR_NO_TMP_DIR'6);

if (!
defined('UPLOAD_ERR_CANT_WRITE'))
    
define('UPLOAD_ERR_CANT_WRITE'7);

define('FILE_UPLOAD_ERR_PATH'10);
define('FILE_UPLOAD_ERR_SIZE'11);
define('FILE_UPLOAD_ERR_TYPE'12);
define('FILE_UPLOAD_ERR_INVALID'13);

class 
File_upload {

    var 
$path;

    var 
$_allowed;
    var 
$_max_size;

    var 
$_is_error//(bool)
    
var $_errno;

    function 
File_upload() {
        
$this->_allowed_mime = array();
        
$this->_allowed_ext  = array();
        
$this->_is_error     false;
        
$this->_errno        0;
        
$this->path          '';
        
$this->_max_size     100000;
    }

    function 
allow($type) {
    
        switch (
$type) {
            case 
'images' :
                
$this->_allowed['image/gif']  = array('gif');
                
$this->_allowed['image/png']  = array('png');
                
$this->_allowed['image/jpeg'] = array('jpg''jpeg');
                
$this->_allowed['image/pjpeg'] = $this->_allowed['image/jpeg'];
                break;
            case 
'text' :
                
$this->_allowed['plain/text'] = array('txt');
                
$this->_allowed['text/plain'] = $this->_allowed['plain/text'];
                break;
        }
    }

    function 
add_allowed($mime$ext) {
        
$this->_allowed[$mime] = $ext;
    }
    function 
get_extensions() {
        
$all_ext = array();
        foreach (
$this->_allowed as $exts)
            foreach(
$exts as $ext)
                
$all_ext[] = $ext;
        return 
$all_ext;
    }

    function 
upload($file) {
        
extract($file);
        
// $type, $name, $tmp_name, $size, $error

        
if (UPLOAD_ERR_OK!=$error) {
            
$this->_is_error true;
            
$this->_errno    $error;
            return 
false;
        }
        
$path $this->get_path();
        if (!
is_dir($path) || $path=='') {
            
$this->_is_error true;
            
$this->_errno    FILE_UPLOAD_ERR_PATH;
            return 
false;
        }
        if (
$size>$this->get_max_size()) {
            
$this->_is_error true;
            
$this->_errno    FILE_UPLOAD_ERR_SIZE;
            return 
false;
        }

        if (!isset(
$this->_allowed[$type])) {
            
$this->_is_error true;
            
$this->_errno    FILE_UPLOAD_ERR_TYPE;
            return 
false;
        }
        
        
$ext strtolower(File_upload::file_extension($name));
        if (!
$ext || !in_array($ext$this->_allowed[$type])) {
            
$this->_is_error true;
            
$this->_errno    FILE_UPLOAD_ERR_TYPE;
            return 
false;
        }

        if (!
is_uploaded_file($tmp_name)) {
            
$this->_is_error true;
            
$this->_errno    FILE_UPLOAD_ERR_INVALID;
            return 
false;
        }


        
// cleanup file name to be cool
        
$name preg_replace('/[^a-zA-Z0-9. ]+/','_',$name); 
        
        
// auto rename
        
$name File_upload::unique_filename($path$name);
        
        
move_uploaded_file($tmp_name$path.$name);

        
// extra paranoid to prevent any execution ever
        
chmod($path.$name0644);

        return 
$name;
    }

    function 
upload_multiple($files) {
        
$total count($files['name']);
        
$filenames = array();
        for (
$x=0$x<$total$x++) {
            
$filenames[] = $this->upload( array(
                
'name' => $files['name'][$x],
                
'type' => $files['type'][$x],
                
'tmp_name' => $files['tmp_name'][$x],
                
'error'    => $files['error'][$x],
                
'size'     => $files['size'][$x],
            ));
        }
        return 
$filenames;
    }

    function 
file_extension($file) {
        
$ext array_pop(explode("."$file));
        if (
$ext==$file)
            return 
false;
        return 
$ext;
    }

    function 
set_max_size($size=0) { $this->_max_size $size; }
    function 
get_max_size()        { return $this->_max_size; }

    function 
get_error() {
        switch (
$this->_errno) {
            case 
UPLOAD_ERR_INI_SIZE :
                return 
'The uploaded file exceeds the upload_max_filesize directive in php.ini.';
            case 
UPLOAD_ERR_FORM_SIZE :
                return 
' The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form.';
            case 
UPLOAD_ERR_PARTIAL :
                return 
'The uploaded file was only partially uploaded.';
            case 
UPLOAD_ERR_NO_FILE :
                return 
'No file was uploaded.';
            case 
UPLOAD_ERR_NO_TMP_DIR :
                return 
'Missing a temporary folder.';
            case 
UPLOAD_ERR_CANT_WRITE :
                return 
'Failed to write file to disk.';
            case 
FILE_UPLOAD_ERR_PATH :
                return 
'Upload path is not a directory.';
            case 
FILE_UPLOAD_ERR_SIZE :
                return 
'The uploaded file exceeds the max file size.';
            case 
FILE_UPLOAD_ERR_TYPE:
                return 
'The uploaded file type is invalid.';
            case 
FILE_UPLOAD_ERR_INVALID:
                return 
'The file is not an actual uploaded file.';
        }
        return 
'Unknown error ('.intval($this->errno).')';
    }

    function 
is_error()      { return $this->_is_error; }
    function 
set_path($path) { $this->path $path; }
    function 
get_path()      { return $this->path; }
    
    function 
unique_filename($path$name) {

        if (!
file_exists($path.$name))
            return 
$name;

        return 
File_upload::unique_filename($pathmd5(time().rand()).$name);
    }

}


?>
fci is offline   Reply With Quote
Reply

Bookmarks

Jump To Top of Thread


Thread Tools
Rate This Thread
Rate This Thread:

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT +1. The time now is 09:22 PM.


Advertisement
Log in to turn off these ads.