PHP-Image - Uploading more than one files per record
Discuss Uploading more than one files per record in the PHP Development forum on Dev Shed. Uploading more than one files per record PHP Development forum discussing coding practices, tips on PHP, and other PHP-related topics. PHP is an open source scripting language that has taken the web development industry by storm.
Posts: 56
Time spent in forums: 13 h 10 m 2 sec
Reputation Power: 1
PHP-Image - Uploading more than one files per record
Hi,
I am very unexperienced in php coding.
I have a code am trying to modify in order to allow writing more than one file to a MySQL database. Initially, the code was able to upload one file to a location on the local machine while writing its name into the mysql database. But I want to expand the code to upload two more files for the same record (i.e uploading three files per record).
Here is the upload.php code
PHP Code:
<?php
// Start a session for error reporting
session_start();
// Check to see if the type of file uploaded is a valid image type
function is_valid_type($file)
{
// This is an array that holds all the valid image MIME types
$valid_types = array("image/jpg", "image/jpeg", "image/bmp", "image/gif");
$valid_types = array("image2/jpg", "image2/jpeg", "image2/bmp", "image2/gif");
$valid_types = array("image3/jpg", "image3/jpeg", "image3/bmp", "image3/gif");
if (in_array($file['type'], $valid_types))
return 1;
return 0;
}
// Just a short function that prints out the contents of an array in a manner that's easy to read
// I used this function during debugging but it serves no purpose at run time for this example
function showContents($array)
{
echo "<pre>";
print_r($array);
echo "</pre>";
}
// Set some constants
// This variable is the path to the image folder where all the images are going to be stored
// Note that there is a trailing forward slash
$TARGET_PATH = "images/";
// Build our target path full string. This is where the file will be moved do
// i.e. images/picture.jpg
$TARGET_PATH .= $image['name'];
$TARGET_PATH .= $image2['name2'];
$TARGET_PATH .= $image3['name3'];
// Make sure all the fields from the form have inputs
if ( $ctitle == "" || $csubject == "" || $creference == "" || $cyear == "" || $cwidth == "" || $cheight == "" || $cperiod == "" || $cdescription == "" || $image['name'] == "" || $image2['name2'] == "" || $image3['name3'] == "" )
{
$_SESSION['error'] = "All fields are required";
header("Location: index.php");
exit;
}
// Check to make sure that our file is actually an image
// You check the file type instead of the extension because the extension can easily be faked
if (!is_valid_type($image))
{
$_SESSION['error'] = "You must upload a jpeg, gif, or bmp";
header("Location: insert.php");
exit;
}
// Here we check to see if a file with that name already exists
// You could get past filename problems by appending a timestamp to the filename and then continuing
if (file_exists($TARGET_PATH))
{
$_SESSION['error'] = "A file with that name already exists";
header("Location: insert.php");
exit;
}
// Lets attempt to move the file from its temporary directory to its new home
if (move_uploaded_file($image['tmp_name'], $TARGET_PATH))
{
// NOTE: This is where a lot of people make mistakes.
// We are *not* putting the image into the database; we are putting a reference to the file's location on the server
$sql = "insert into collections (ctitle, csubject, creference, cyear, cwidth, cheight, cperiod, cdescription, cfilename, cfilename2, cfilename3) values ('$ctitle', '$csubject', '$creference', '$cyear', '$cwidth', '$cheight', '$cperiod', '$cdescription', '" . $image['name'] . "', '" . $image2['name2'] . "', '" . $image3['name3'] . "')";
$result = mysql_query($sql) or die ("Could not insert data into DB: " . mysql_error());
header("Location: index.php");
exit;
}
else
{
// A common cause of file moving failures is because of bad permissions on the directory attempting to be written to
// Make sure you chmod the directory to be writeable
$_SESSION['error'] = "Could not upload file. Check read/write persmissions on the directory";
header("Location: index.php");
exit;
}
?>
Posts: 7,930
Time spent in forums: 2 Months 7 h 39 m 37 sec
Reputation Power: 6991
Thanks for taking an initial stab at it yourself and posting what you came up with.
Let me start by saying that your script, even without the modifications you made, is completely insecure and hopefully is not live in a production environment right now. I'm not sure who programmed it originally, but I'm assuming it probably wasn't you.
I will start with that security problem first:
Quote:
// You check the file type instead of the extension because the extension can easily be faked
This statement is completely false. You never check the file type instead of the extension. Yes, the extension of a file can be faked; but so can the file type, and when it comes to exploits in file uploads the file type does not matter ever, but the extension of the file matters very very much.
So the first issue in your script is that function:
PHP Code:
// Check to see if the type of file uploaded is a valid image type
function is_valid_type($file)
{
// This is an array that holds all the valid image MIME types
$valid_types = array("image/jpg", "image/jpeg", "image/bmp", "image/gif");
$valid_types = array("image2/jpg", "image2/jpeg", "image2/bmp", "image2/gif");
$valid_types = array("image3/jpg", "image3/jpeg", "image3/bmp", "image3/gif");
if (in_array($file['type'], $valid_types))
return 1;
return 0;
}
The $valid_types array is not tied to a specific file upload box. The "image" in "image/jpeg" is not related in any way to the fact that your file box is named "image". Additionally, with the modifications you made you are overwriting the $valid_types array twice, so the first two declarations of it are effectively missing. Since "image3/jpg" is not a valid MIME type, that function won't work.
Additionally, there is the security issue I mentioned before.
PHP Code:
// Check to see if the type of file uploaded is a valid image type
function is_valid_type($file)
{
// This is an array that holds all the valid image MIME types
// These are the same for all file upload boxes
$valid_types = array("image/jpg", "image/jpeg", "image/bmp", "image/gif");
// This is an array that holds all valid image extensions
// These are the same for all file upload boxes
$valid_exts = array('jpg', 'jpeg', 'bmp', 'gif');
// This check is optional
if(!in_array($file['type'], $valid_types))
return 0;
// Get the extension from the uploaded filename
$upload_ext = pathinfo($file['name'], PATHINFO_EXTENSION);
// This check is essential for security
if(!in_array($upload_ext, $valid_exts))
return 0;
return 1;
}
The next issue is with this section:
PHP Code:
// Build our target path full string. This is where the file will be moved do
// i.e. images/picture.jpg
$TARGET_PATH .= $image['name'];
$TARGET_PATH .= $image2['name2'];
$TARGET_PATH .= $image3['name3'];
The . operator concatenates strings together. Note that $a .= $b is shorthand for $a = $a . $b; In this case, you're going to end up with something like "images/filename1filename2filename3", which isn't going to help you much. You need three separate target path variables, one per image.
These is another logical error that exists in both the original version of this script and in your modifications:
// Build our target path full string. This is where the file will be moved do
// i.e. images/picture.jpg
$TARGET_PATH .= $image['name'];
$TARGET_PATH .= $image2['name2'];
$TARGET_PATH .= $image3['name3'];
You do not want to call mysql_real_escape_string on ['name'] before you use it to define the target path. Otherwise you could end up with backslashes in your filename, which is an annoyance on Linux and a massive problem on Windows. Fortunately, in this particular script that is easy enough to solve by swapping the order of those two sections:
PHP Code:
// Build our target path full string. This is where the file will be moved do
// i.e. images/picture.jpg
$TARGET_PATH .= $image['name'];
$TARGET_PATH .= $image2['name2'];
$TARGET_PATH .= $image3['name3'];
// Build our target path full string. This is where the file will be moved do
// i.e. images/picture.jpg
$target_path_1 = $TARGET_PATH . $image['name'];
$target_path_2 = $TARGET_PATH . $image2['name2'];
$target_path_3 = $TARGET_PATH . $image3['name3'];
These two checks need to be repeated for each of your uploaded files:
PHP Code:
// Check to make sure that our file is actually an image
// You check the file type instead of the extension because the extension can easily be faked
if (!is_valid_type($image))
{
$_SESSION['error'] = "You must upload a jpeg, gif, or bmp";
header("Location: insert.php");
exit;
}
// Here we check to see if a file with that name already exists
// You could get past filename problems by appending a timestamp to the filename and then continuing
if (file_exists($TARGET_PATH))
{
$_SESSION['error'] = "A file with that name already exists";
header("Location: insert.php");
exit;
}
See how is_valid_type is only called on $image and not on $image2 or $image3. Also see how only $TARGET_PATH is checked in the second if block.
For the first part, you can easily re-use the function for each image:
PHP Code:
if (!is_valid_type($image) || !is_valid_type($image2) || !is_valid_type($image3))
{
$_SESSION['error'] = "You must upload a jpeg, gif, or bmp";
header("Location: insert.php");
exit;
}
You can do something similar for the second part:
PHP Code:
if (file_exists($target_path_1) || file_exists($target_path_2) || file_exists($target_path_3))
{
$_SESSION['error'] = "A file with that name already exists";
header("Location: insert.php");
exit;
}
Remember that we now have three separate variables for storing the uploaded file paths.
The last section needs modified to handle all three files too:
PHP Code:
// Lets attempt to move the file from its temporary directory to its new home
if (move_uploaded_file($image['tmp_name'], $TARGET_PATH))
{
// NOTE: This is where a lot of people make mistakes.
// We are *not* putting the image into the database; we are putting a reference to the file's location on the server
$sql = "insert into collections (ctitle, csubject, creference, cyear, cwidth, cheight, cperiod, cdescription, cfilename, cfilename2, cfilename3) values ('$ctitle', '$csubject', '$creference', '$cyear', '$cwidth', '$cheight', '$cperiod', '$cdescription', '" . $image['name'] . "', '" . $image2['name2'] . "', '" . $image3['name3'] . "')";
$result = mysql_query($sql) or die ("Could not insert data into DB: " . mysql_error());
header("Location: index.php");
exit;
}
else
{
// A common cause of file moving failures is because of bad permissions on the directory attempting to be written to
// Make sure you chmod the directory to be writeable
$_SESSION['error'] = "Could not upload file. Check read/write persmissions on the directory";
header("Location: index.php");
exit;
}
The first part of this, move_uploaded_file, is what actually copies the uploaded file into its permanent location on the disk. You need to call this three times, one per uploaded file. However, you do not want to call the SQL query more than once, because all three images belong to the same record in the database.
PHP Code:
// Lets attempt to move the file from its temporary directory to its new home
if (
move_uploaded_file($image['tmp_name'], $target_path_1)
&& move_uploaded_file($image2['tmp_name'], $target_path_2)
&& move_uploaded_file($image3['tmp_name'], $target_path_3)
)
{
// NOTE: This is where a lot of people make mistakes.
// We are *not* putting the image into the database; we are putting a reference to the file's location on the server
$sql = "insert into collections (ctitle, csubject, creference, cyear, cwidth, cheight, cperiod, cdescription, cfilename, cfilename2, cfilename3) values ('$ctitle', '$csubject', '$creference', '$cyear', '$cwidth', '$cheight', '$cperiod', '$cdescription', '" . $image['name'] . "', '" . $image2['name2'] . "', '" . $image3['name3'] . "')";
$result = mysql_query($sql) or die ("Could not insert data into DB: " . mysql_error());
header("Location: index.php");
exit;
}
else
{
// A common cause of file moving failures is because of bad permissions on the directory attempting to be written to
// Make sure you chmod the directory to be writeable
$_SESSION['error'] = "Could not upload file. Check read/write persmissions on the directory";
header("Location: index.php");
exit;
}
Code:
<td> <input type="file" name="image2" /><br />
This might be a consequence of how you pasted the code into the forum, but make sure you do not actually have those color tags in your HTML.
Posts: 56
Time spent in forums: 13 h 10 m 2 sec
Reputation Power: 1
Uploading more than one files per record
Hi E-Oreo,
Thanx alot for for help. However, I could not get the updated code working to include two more image uploads for each record. But again when I remain with only the code that uploads the first image, the code works fine.
Here is the latest code after your advise:
PHP Code:
<?php
// Start a session for error reporting
session_start();
// Check to see if the type of file uploaded is a valid image type
function is_valid_type($file)
{
// This is an array that holds all the valid image MIME types
// These are the same for all file upload boxes
$valid_types = array("image/jpg", "image/jpeg", "image/bmp", "image/gif");
// This is an array that holds all valid image extensions
// These are the same for all file upload boxes
$valid_exts = array('jpg', 'jpeg', 'bmp', 'gif');
// This check is optional
if(!in_array($file['type'], $valid_types))
return 0;
// Get the extension from the uploaded filename
$upload_ext = pathinfo($file['name'], PATHINFO_EXTENSION);
// This check is essential for security
if(!in_array($upload_ext, $valid_exts))
return 0;
return 1;
}
// Just a short function that prints out the contents of an array in a manner that's easy to read
// I used this function during debugging but it serves no purpose at run time for this example
function showContents($array)
{
echo "<pre>";
print_r($array);
echo "</pre>";
}
// Set some constants
// This variable is the path to the image folder where all the images are going to be stored
// Note that there is a trailing forward slash
$TARGET_PATH = "images/";
// Build our target path full string. This is where the file will be moved do
// i.e. images/picture.jpg
$target_path_1 = $TARGET_PATH . $image['name'];
$target_path_2 = $TARGET_PATH . $image2['name2'];
$target_path_3 = $TARGET_PATH . $image3['name3'];
// Make sure all the fields from the form have inputs
if ( $ctitle == "" || $csubject == "" || $creference == "" || $cyear == "" || $cwidth == "" || $cheight == "" || $cperiod == "" || $cmarkings == "" || $cdescription == "" || $image['name'] == "" || $image2['name2'] == "" || $image3['name3'] == "")
{
$_SESSION['error'] = "All fields are required";
header("Location: index.php");
exit;
}
// Check to make sure that our file is actually an image
// You check the file type instead of the extension because the extension can easily be faked
if (!is_valid_type($image) || !is_valid_type($image2) || !is_valid_type($image3))
{
$_SESSION['error'] = "You must upload a jpeg, gif, or bmp";
header("Location: insert.php");
exit;
}
// Here we check to see if a file with that name already exists
// You could get past filename problems by appending a timestamp to the filename and then continuing
if (file_exists($target_path_1) || file_exists($target_path_2) || file_exists($target_path_3))
{
$_SESSION['error'] = "A file with that name already exists";
header("Location: insert.php");
exit;
}
// Lets attempt to move the file from its temporary directory to its new home
if (
move_uploaded_file($image['tmp_name'], $target_path_1)
&& move_uploaded_file($image2['tmp_name'], $target_path_2)
&& move_uploaded_file($image3['tmp_name'], $target_path_3)
)
{
// NOTE: This is where a lot of people make mistakes.
// We are *not* putting the image into the database; we are putting a reference to the file's location on the server
$sql = "insert into collections (ctitle, csubject, creference, cyear, cwidth, cheight, cperiod, cdescription, cfilename, cfilename2, cfilename3) values ('$ctitle', '$csubject', '$creference', '$cyear', '$cwidth', '$cheight', '$cperiod', '$cdescription', '" . $image['name'] . "', '" . $image2['name2'] . "', '" . $image3['name3'] . "')";
$result = mysql_query($sql) or die ("Could not insert data into DB: " . mysql_error());
header("Location: index.php");
exit;
}
else
{
// A common cause of file moving failures is because of bad permissions on the directory attempting to be written to
// Make sure you chmod the directory to be writeable
$_SESSION['error'] = "Could not upload file. Check read/write persmissions on the directory";
header("Location: index.php");
exit;
}
?>
Posts: 56
Time spent in forums: 13 h 10 m 2 sec
Reputation Power: 1
Uploading more than one files per record
Hi E-Oreo,
Below is the updated code, but this time it does not insert the record. Instead, the input controls on the insert.php page gets its data cleared upon clicking the submit button.
PHP Code:
<?php
// Start a session for error reporting
session_start();
// Check to see if the type of file uploaded is a valid image type .........................
function is_valid_type($file)
{
// This is an array that holds all the valid image MIME types
// These are the same for all file upload boxes
$valid_types = array("image/jpg", "image/jpeg", "image/bmp", "image/gif");
// This is an array that holds all valid image extensions
// These are the same for all file upload boxes
$valid_exts = array('jpg', 'jpeg', 'bmp', 'gif');
// This check is optional
if(!in_array($file['type'], $valid_types))
return 0;
// Get the extension from the uploaded filename
$upload_ext = pathinfo($file['name'], PATHINFO_EXTENSION);
// This check is essential for security
if(!in_array($upload_ext, $valid_exts))
return 0;
return 1;
}
//...................................................................................................
// Just a short function that prints out the contents of an array in a manner that's easy to read
// I used this function during debugging but it serves no purpose at run time for this example
function showContents($array)
{
echo "<pre>";
print_r($array);
echo "</pre>";
}
// Set some constants
// This variable is the path to the image folder where all the images are going to be stored
// Note that there is a trailing forward slash
$TARGET_PATH = "images/";
// Build our target path full string. This is where the file will be moved do
// i.e. images/picture.jpg
$target_path_1 = $TARGET_PATH . $image['name'];
$target_path_2 = $TARGET_PATH . $image2['name'];
$target_path_3 = $TARGET_PATH . $image3['name'];
// Make sure all the fields from the form have inputs
if ( $ctitle == "" || $csubject == "" || $creference == "" || $cyear == "" || $cwidth == "" || $cheight == "" || $cperiod == "" || $cmarkings == "" || $cdescription == "" || $image['name'] == "" || $image2['name'] == "" || $image3['name'] == "")
{
$_SESSION['error'] = "All fields are required";
header("Location: index.php");
exit;
}
// Check to make sure that our file is actually an image
// You check the file type instead of the extension because the extension can easily be faked
if (!is_valid_type($image) || !is_valid_type($image2) || !is_valid_type($image3))
{
$_SESSION['error'] = "You must upload a jpeg, gif, or bmp";
header("Location: insert.php");
exit;
}
// Here we check to see if a file with that name already exists
// You could get past filename problems by appending a timestamp to the filename and then continuing
if (file_exists($target_path_1) || file_exists($target_path_2) || file_exists($target_path_3))
{
$_SESSION['error'] = "A file with that name already exists";
header("Location: insert.php");
exit;
}
// Lets attempt to move the file from its temporary directory to its new home
if (
move_uploaded_file($image['tmp_name'], $target_path_1)
&& move_uploaded_file($image2['tmp_name'], $target_path_2)
&& move_uploaded_file($image3['tmp_name'], $target_path_3)
)
{
// NOTE: This is where a lot of people make mistakes.
// We are *not* putting the image into the database; we are putting a reference to the file's location on the server
$sql = "insert into collections (ctitle, csubject, creference, cyear, cwidth, cheight, cperiod, cdescription, cfilename, cfilename2, cfilename3) values ('$ctitle', '$csubject', '$creference', '$cyear', '$cwidth', '$cheight', '$cperiod', '$cdescription', '" . $image['name'] . "', '" . $image2['name'] . "', '" . $image3['name'] . "')";
$result = mysql_query($sql) or die ("Could not insert data into DB: " . mysql_error());
header("Location: index.php");
exit;
}
else
{
// A common cause of file moving failures is because of bad permissions on the directory attempting to be written to
// Make sure you chmod the directory to be writeable
$_SESSION['error'] = "Could not upload file. Check read/write persmissions on the directory";
header("Location: index.php");
exit;
}
?>