Solved

PHP - copy temporary uploaded file not working

Posted on 2011-09-29
9
248 Views
Last Modified: 2012-05-12
My website submission form e-mails the text fields to me.
An additional field uploads a file to my server.

The form works and produces no errors but the files are not copied to the designated directory.

Form field: <input type="file" name="photo" size="30" />

	$tmpname = $_FILES['photo']['name']; //I added this for testing
	echo ($tmpname); //this returns empty
	
	$photoname = $_FILES['photo']['name'];
	$photoextension = $_FILES['photo']['type'];
	echo ($photoname.$photoextension); //added for testing, this works fine
	$photourl = "venueuploads/".$photoname.$photoextension;
	echo ($photourl); //this works and returns the full file name
	$photo = copy ($_FILES['photo']['tmp_name']['type'], $photourl); //this does not work

Open in new window

0
Comment
Question by:IBMKenobi
  • 4
  • 4
9 Comments
 
LVL 50

Expert Comment

by:Steve Bink
ID: 36870160
I think you're looking for move_uploaded_file().
0
 
LVL 108

Expert Comment

by:Ray Paseur
ID: 36890769
File uploads have security implications and require some fairly specific error checking and visualization.  This script shows how to do a file upload (or three).   Note the man page references in the comments.  You will want to read those carefully to understand all the moving parts.  You can copy this script and customize it for your own use.  Pay particular attention to the initialization of variables before line 30.

HTH, and please post back with any specific questions, ~Ray
<?php // RAY_upload_example.php
error_reporting(E_ALL);


// MANUAL REFERENCE PAGES YOU MUST UNDERSTAND TO UPLOAD FILES
// http://php.net/manual/en/features.file-upload.php
// http://php.net/manual/en/features.file-upload.common-pitfalls.php
// http://php.net/manual/en/function.move-uploaded-file.php


// PHP 5.1+  SEE http://php.net/manual/en/function.date-default-timezone-set.php
date_default_timezone_set('America/Chicago');

// ESTABLISH THE NAME OF THE 'uploads' DIRECTORY
$uploads = 'RAY_junk';

// ESTABLISH THE BIGGEST FILE SIZE WE CAN ACCEPT - ABOUT 8 MB
$max_file_size = '8192000';

// ESTABLISH THE MAXIMUM NUMBER OF FILES WE CAN UPLOAD
$nf = 3;

// ESTABLISH THE KINDS OF FILE EXTENSIONS WE CAN ACCEPT
$file_exts = array
( 'jpg'
, 'gif'
, 'png'
, 'txt'
, 'pdf'
)
;

// LIST OF THE ERRORS THAT MAY BE REPORTED IN $_FILES[]["error"] (THERE IS NO #5)
$errors = array
( 0 => "Success!"
, 1 => "The uploaded file exceeds the upload_max_filesize directive in php.ini"
, 2 => "The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form"
, 3 => "The uploaded file was only partially uploaded"
, 4 => "No file was uploaded"
, 5 => "UNDEFINED ERROR"
, 6 => "Missing a temporary folder"
, 7 => "Cannot write file to disk"
)
;




// IF THERE IS NOTHING IN $_POST, PUT UP THE FORM FOR INPUT
if (empty($_POST))
{
    ?>
    <h2>Upload <?php echo $nf; ?> file(s)</h2>

    <!--
        SOME THINGS TO NOTE ABOUT THIS FORM...
        ENCTYPE IN THE HTML <FORM> STATEMENT
        MAX_FILE_SIZE MUST PRECEDE THE FILE INPUT FIELD
        INPUT NAME= IN TYPE=FILE DETERMINES THE NAME YOU FIND IN $_FILES ARRAY
        ABSENCE OF ACTION= ATTRIBUTE IN FORM TAG CAUSES POST TO SAME SCRIPT
    -->

    <form name="UploadForm" enctype="multipart/form-data" method="post">
    <input type="hidden" name="MAX_FILE_SIZE" value="<?php echo $max_file_size; ?>" />
    <p>
    Find the file(s) you want to upload and click the "Upload" button below.
    </p>

    <?php // CREATE INPUT STATEMENTS FOR UP TO $n FILE NAMES
    for ($n = 0; $n < $nf; $n++)
    {
        echo "<input name=\"userfile$n\" type=\"file\" size=\"80\" /><br/>\n";
    }
    ?>

    <br/>Check this box <input autocomplete="off" type="checkbox" name="overwrite" /> to <strong>overwrite</strong> existing files.
    <input type="submit" value="Upload" />
    </form>
    <?php
    die();
}
// END OF THE FORM SCRIPT



// WE HAVE GOT SOMETHING IN $_POST - RUN THE ACTION SCRIPT
else
{
    // THERE IS POST DATA - PROCESS IT
    echo "<h2>Results: File Upload</h2>\n";

    // ACTIVATE THIS TO SEE WHAT IS COMING THROUGH
    //    echo "<pre>"; var_dump($_FILES); var_dump($_POST); echo "</pre>\n";

    // ITERATE OVER THE CONTENTS OF $_FILES
    foreach ($_FILES as $my_uploaded_file)
    {
        // SKIP OVER EMPTY SPOTS - NOTHING UPLOADED
        $error_code    = $my_uploaded_file["error"];
        if ($error_code == 4) continue;

        // SYNTHESIZE THE NEW FILE NAME
        $f_type    = trim(strtolower(end    (explode( '.', basename($my_uploaded_file['name'] )))));
        $f_name    = trim(strtolower(current(explode( '.', basename($my_uploaded_file['name'] )))));
        $my_new_file = getcwd() . '/' . $uploads . '/' . $f_name . '.' . $f_type;
        $my_file     =                  $uploads . '/' . $f_name . '.' . $f_type;

        // OPTIONAL TEST FOR ALLOWABLE EXTENSIONS
        if (!in_array($f_type, $file_exts)) die("Sorry, $f_type files not allowed");

        // IF THERE ARE ERRORS
        if ($error_code != 0)
        {
            $error_message = $errors[$error_code];
            die("Sorry, Upload Error Code: $error_code: $error_message");
        }

        // GET THE FILE SIZE
        $file_size = number_format($my_uploaded_file["size"]);

        // IF THE FILE IS NEW (DOES NOT EXIST)
        if (!file_exists($my_new_file))
        {
            // IF THE MOVE FUNCTION WORKED CORRECTLY
            if (move_uploaded_file($my_uploaded_file['tmp_name'], $my_new_file))
            {
                $upload_success = 1;
            }
            // IF THE MOVE FUNCTION FAILED
            else
            {
                $upload_success = -1;
            }
        }

        // IF THE FILE ALREADY EXISTS
        else
        {
            echo "<br/><b><i>$my_file</i></b> already exists.\n";

            // SHOULD WE OVERWRITE THE FILE? IF NOT
            if (empty($_POST["overwrite"]))
            {
                $upload_success = 0;
            }
            // IF WE SHOULD OVERWRITE THE FILE, TRY TO MAKE A BACKUP
            else
            {
                $now    = date('Y-m-d');
                $my_bak = $my_new_file . '.' . $now . '.bak';
                if (!copy($my_new_file, $my_bak))
                {
                    echo "<br/><strong>Attempted Backup Failed!</strong>\n";
                }
                if (move_uploaded_file($my_uploaded_file['tmp_name'], $my_new_file))
                {
                    $upload_success = 2;
                }
                else
                {
                    $upload_success = -1;
                }
            }
        }

        // REPORT OUR SUCCESS OR FAILURE
        if ($upload_success == 2) { echo "<br/>It has been overwritten.\n"; }
        if ($upload_success == 1) { echo "<br/><strong>$my_file</strong> has been saved.\n"; }
        if ($upload_success == 0) { echo "<br/><strong>It was NOT overwritten.</strong>\n"; }
        if ($upload_success < 0)  { echo "<br/><strong>ERROR: $my_file NOT SAVED - SEE WARNING FROM move_uploaded_file() COMMAND</strong>\n"; }
        if ($upload_success > 0)
        {
            echo "$file_size bytes uploaded.\n";
            if (!chmod ($my_new_file, 0755))
            {
                echo "<br/>chmod(0755) FAILED: fileperms() = ";
                echo substr(sprintf('%o', fileperms($my_new_file)), -4);
            }
            echo "<br/><a href=\"$my_file\">See the file $my_file</a>\n";
        }
    // END FOREACH ITERATOR - EACH ITERATION PROCESSES ONE FILE
    }
}

Open in new window

0
 
LVL 4

Author Comment

by:IBMKenobi
ID: 36902186
Thanks for the comments but the file still won't move.

No errors are produced either, either from E_ALL or the list given above.

$_FILES['tmp_name'] doesn't exist either but $_FILES['name'] displays the original file name.

0
 
LVL 108

Expert Comment

by:Ray Paseur
ID: 36902986
It might be that you have the wrong directory permissions. The script I posted works correctly, but obviously it will fail if the $uploads directory is not writable.  It will issue an error message on line 170 if move_uploaded_file() failed.

Show us the input data and the entire HTML form that submits the input data.  Then add this to the top of your PHP action script, run it again and show us the output.

ini_set('display_errors', TRUE);
error_reporting(E_ALL);
echo "<pre>";
var_dump($_FILES);
var_dump($_POST);
var_dump($_GET);

You might also want to put the script on a test location and post the URL here.  That should be enough information to shed some light on it.
0
IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

 
LVL 4

Author Comment

by:IBMKenobi
ID: 36903123
Running the most basic version of the script with the details above the script works.
When run along with the rest of the code on the page the tmp_name field is unavailable.

<body>
<?PHP
if ( isset($_POST['submitlisting']) ){

ini_set('display_errors', TRUE);
error_reporting(E_ALL);
echo "<pre>";
var_dump($_FILES);
var_dump($_POST);
var_dump($_GET);

$photo = $_FILES['photo'];
	$url = '/absoluteurl/';
	$newurl = $url.'venueuploads/'.$photo['name'];
	echo ($newurl.'<br />');
	
		if (move_uploaded_file ($photo['tmp_name'], $newurl)) {
			echo ('File moved<br /><br />');
		}else{
			echo ('File move failed<br /><br />');
		}

}
?>

<form action="<?php echo $PHP_SELF;?>" method="post" enctype="multipart/form-data">
<input type='hidden' name="MAX_FILE_SIZE" value="307200" />
    <p><label>Add Photo:</label><input type="file" name="photo" size="30" /> <span class="smallnote">JPG,GIF,PNG format, max 3mb</span></p>
<p class="smalltext">
	  <label></label>
	  <input type="submit" name="submitlisting" value="Add Premium Details" />
	</p>
  </form>
</body>

[b]Output:[/b]
array(1) {
  ["photo"]=>
  array(5) {
    ["name"]=>
    string(22) "fb_advert_shamrock.gif"
    ["type"]=>
    string(9) "image/gif"
    ["tmp_name"]=>
    string(14) "/tmp/phpbb790e"
    ["error"]=>
    int(0)
    ["size"]=>
    int(7462)
  }
}
array(2) {
  ["MAX_FILE_SIZE"]=>
  string(6) "307200"
  ["submitlisting"]=>
  string(19) "Add Premium Details"
}
array(0) {
}
/absoluteurl/venueuploads/fb_advert_shamrock.gif
File moved

Open in new window

0
 
LVL 4

Author Comment

by:IBMKenobi
ID: 36903158
Full HTML Form:
<form action="<?php echo $PHP_SELF;?>" method="post" enctype="multipart/form-data">
<input type='hidden' name="MAX_FILE_SIZE" value="3072" />
      <p><label>First Name:</label><input type="text" name="fname" size="30" maxlength="50" />* <span class="smallnote">(Not publicly displayed)</span></p>
      <p><label>Last Name:</label><input type="text" name="lname" size="30" maxlength="50" />* <span class="smallnote">(Not publicly displayed)</span></p>
      <p><label>Your E-mail Address:</label><input type="text" name="useremail" size="30" maxlength="50" /><span class="smallnote">(Not publicly displayed)</span></p>
      <p><label>Venue Name:</label><input type="text" name="venue" size="30" maxlength="50" />*</p>
      <p><label>Address:</label><textarea name="address" cols="30" rows="4"></textarea>*</p>
    <p><label>County:</label><select name="county" size="8">
                <?PHP
while ($row = mysql_fetch_array($counties) ) {
echo ('<option value="'.$row['county'].'">' .$row['county']. '</option>');
}
?>
              </select>*</p>
    <p><label>Website:</label><input type="text" name="website" size="30" maxlength="50" />*</p>
    <p><label>Telephone:</label><input type="text" name="telephone" size="30" maxlength="50" />*</p>
    <p><label>Public E-mail Address:</label><input type="text" name="publicemail" size="30" maxlength="50" />*</p>
    <p><label>Facebook ID:</label><input type="text" name="facebook" size="30" maxlength="50" /></p>
    <p><label>Twitter Name:</label><input type="text" name="twitter" size="30" maxlength="50" /></p>
    <p><label>Add Photo:</label><input type="file" name="photo" size="30" /> <span class="smallnote">JPG,GIF,PNG format, max 3mb</span></p>
    <p><label>Add Menu:</label><input type="file" name="menu" size="30" /> <span class="smallnote">doc,docx,pdf,txt format, max 3mb</span></p>
    <p><label>Catering Level:</label><select name="venuelevel" size="7">
                <?PHP
while ($row = mysql_fetch_array($venuelevel) ) {
echo ('<option value="'.$row['venuelevel'].'">' .$row['venuelevel']. '</option>');
}
?>
              </select>*</p>
      <p class="smalltext">
        <label></label>
        <input type="submit" name="submitlisting" value="Add Premium Details" />
      </p>
  </form>

Full Code:
<?PHP
/* Submits form contents to email address */
if ( isset($_POST['submitlisting']) ){

	$from = ini_set('sendmail_from',$_POST['email']);

	$to = 'target@email.address';
	if (!preg_match("/^target@email.address$/D", $to)) die('3');

 	$subject = 'Premium Listing Purchase';
 	if (!preg_match("/^Premium Listing Purchase$/D", $subject)) die('4');

 	$fname = $_POST['fname'];
 	if (!preg_match("/[a-zA-Z ]/", $fname)) die('Your first name can only contain letters');

 	$lname = $_POST['lname'];
 	if (!preg_match("/[a-zA-Z ]/", $lname)) die('Your last name can only contain letters');

	$useremail = $_POST['useremail'];
	if (!preg_match('#^[a-z0-9.!\#$%&\'*+-/=?^_`{|}~]+@([0-9.]+|([^\s]+\.+[a-z]{2,6}))$#si', $useremail)) die('user email 2');
	
	$venue = $_POST['venue'];
 	if (!preg_match("/[a-zA-Z0-9 \']/", $venue)) die('Your venue can only contain letters and numbers');

	$address = $_POST['address'];
 	if (!preg_match("/[a-zA-Z0-9 ]/", $address)) die('Your address can only contain letters and numbers');

	$county = $_POST['county'];
 	if (!preg_match("/[a-zA-Z0-9 ]/", $county)) die('Your county can only contain letters');

	$website = $_POST['website'];
 	if (!preg_match("/^([\w\-?:\/])/i", $website)) die('Your website can only contain letters, numbers and the symbols :/.');

 	$telephone = $_POST['telephone'];
 	if (!preg_match("/[0-9 ]/", $telephone)) die('The telephone number can only contain numbers');

	$publicemail = $_POST['publicemail'];
 	if (!preg_match('#^[a-z0-9.!\#$%&\'*+-/=?^_`{|}~]+@([0-9.]+|([^\s]+\.+[a-z]{2,6}))$#si', $publicemail)) die('public email 2');

	$facebook = $_POST['facebook'];
 	if (!preg_match("/^[a-zA-Z0-9]?$/", $facebook)) die('Your Facebook ID can only contain letters and numbers');
	
	$twitter = $_POST['twitter'];
 	if (!preg_match("/^[a-zA-Z0-9]?$/", $twitter)) die('Your Twitter name can only contain letters and numbers');
	
	[b]$photo = $_FILES['photo'];
	$url = '/home/linweb04/g/glutenfreeireland.com/user/htdocs/';
	$newurl = $url.'venueuploads/'.$photo['name'];
	echo ($newurl.'<br />');
	
		if (move_uploaded_file ($photo['tmp_name'], $newurl)) {
			echo ('File moved<br /><br />');
		}else{
			echo ('File move failed<br /><br />');
		}[/b]
	
	$venuelevel = $_POST['venuelevel'];
 	if (!preg_match("/[a-zA-Z ]/", $venuelevel)) die('Your catering level can only contain letters');

 	$body = 'Premium Listing Purchase:
	First Name '.$fname.'
 	Last Name: '.$lname.'
 	Account Holder Email: '.$useremail.'
 	Venue: '.$venue.'
 	Address: '.$address.'
 	County: '.$county.'
	Website: '.$website.'
	Telephone: '.$telephone.'
	Public Email: '.$publicemail.'
	Facebook: '.$facebook.'
	Twitter: '.$twitter.'
	Add Photo: http://www.glutenfreeireland.com/venue_uploads/'.$filenamephoto.'
	Add Menu: http://www.glutenfreeireland.com/venue_uploads/'.$filenamemenu.'
	Catering Level: '.$venuelevel;

function contains_bad_str($str_to_test) {
  $bad_strings = array(
                "content-type:"
                ,"mime-version:"
                ,"multipart/mixed"
		,"Content-Transfer-Encoding:"
                ,"bcc:"
		,"cc:"
		
  );
  
  foreach($bad_strings as $bad_string) {
    if(eregi($bad_string, strtolower($str_to_test))) {
      echo ('<p>'.$bad_string.' found. Suspected injection attempt - mail not being sent.</p>');
      exit;
    }
  }
}

function contains_newlines($str_to_test) {
   if(preg_match("/(%0A|%0D|\\n+|\\r+)/i", $str_to_test) != 0) {
     echo ('<p>newline found in '.$str_to_test.' Suspected injection attempt - mail not being sent.</p>');
     exit;
   }
} 
 	
contains_bad_str($from);
contains_bad_str($subject);
contains_bad_str($body);

contains_newlines($from);
contains_newlines($subject);

 		 if (mail($to, $subject, $body, '-f'.$from)) {
   echo('<p>Thank you very much, your premium listing has been successfully submitted<br /><br />
You will receive an e-mail when your listing has been updated (normally within 1 working day).</p>');
  } else {
   echo('<p>Uh-oh, message delivery has failed. Please check your e-mail address is working.<br />
   Alternatively you can e-mail <a href="mailto:target@email.address">target@email.address</a> directly, simply include all of the details required above.</p>');
  }
echo ('
<br />

<div id="footer">');
include 'menu_footer.php';
echo ('
</div>
<!-- END FOOTER -->
</div>

</body>
</html>
');
die();
}
?>

Open in new window

0
 
LVL 108

Accepted Solution

by:
Ray Paseur earned 500 total points
ID: 36903304
Aha!  The culprit might be right here:

<input type='hidden' name="MAX_FILE_SIZE" value="3072" />

Read this page: http://php.net/manual/en/features.file-upload.post-method.php

Max file size is given in bytes.  See the note here: http://php.net/manual/en/features.file-upload.post-method.php#100187
0
 
LVL 4

Author Comment

by:IBMKenobi
ID: 36903420
Oh gag, after all that!

Thanks very much once again for your patience and replies. Some very handy code hints in there too which I'll get to work on.
All the best.
0
 
LVL 108

Expert Comment

by:Ray Paseur
ID: 36903432
It's always simple in hindsight!  Thanks for the points and good luck with your project, ~Ray
0

Featured Post

IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

Suggested Solutions

Generating table dynamically is the most common issue faced by php developers.... So it seems there is a need of an article that explains the basic concept of generating tables dynamically. It just requires a basic knowledge of html and little maths…
Foreword (July, 2015) Since I first wrote this article, years ago, a great many more people have begun using the internet.  They are coming online from every part of the globe, learning, reading, shopping and spending money at an ever-increasing ra…
Explain concepts important to validation of email addresses with regular expressions. Applies to most languages/tools that uses regular expressions. Consider email address RFCs: Look at HTML5 form input element (with type=email) regex pattern: T…
The viewer will learn how to count occurrences of each item in an array.

707 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

16 Experts available now in Live!

Get 1:1 Help Now