Best Way To Store Multiple Uploaded Files in a Database
I currently have a PHP upload form that lets users upload multiple files. This is the backend script that uploads the files.
while(list($key,$value) = each($_FILES[images][name]))
{
if(!empty($value)){ // this will check if any blank field is entered
$filename = $value; // filename stores the value
$filename=str_replace(" ","_",$filename);// Add _ inplace of blank space in file name, you can remove this line
$file_ext = @strtolower(@strrchr($filename,"."));
$file_ext = @substr($file_ext, 1); // remove dot
$filename = md5(uniqid(rand(), true)) . '.' . $file_ext;
$add = "/html/uploaded/$filename"; // upload directory path is set
copy($_FILES[images][tmp_name][$key], $add); // upload the file to the server
chmod("$add",0777);
}
}
After this while loop, I run a SQL query to insert the information into my database. How can I make sure that the first first file is stored as $file1 and the second as $file2, etc.
I tried counting the loop to f开发者_如何学Cigure out which number file was which, but it was not working.
Storing files in the database is generally regarded as a bad idea. You are better served by placing the files on the server's local disc and storing the filename in the database instead.
Looking at your code, it appears that you are actually trying to do it like that, so your question title is a bit of a misnomer.
You have several structural problems with your code. Try this code out:
$errors = array();
$files = array();
foreach ($_FILES['images'] as $k=>$image) {
// handle upload errors
if ($image['error'] != 0 && $image['error'] != 4) {
switch ($image['error']) {
case '1':
case '2':
$err = 'The uploaded file exceeds the maximum file size.';
break;
case '3':
$err = 'The upload was inturupted, transfer failed.';
break;
case '6':
case '7':
case '8':
$err = 'Server error. Please try again later.';
break;
}
// record error and move on
$errors[] = array('image'=>$k, 'error'=>$err);
continue;
} elseif ($image['error'] == 4) {
// error 4 means no image was sent
continue;
}
// determine the extension
$ext = explode('.', $image['name']);
if (count($ext) != 2) {
$errors[] = array('image'=>$k, 'error'=>'Could not determine file extension.');
continue;
} else {
switch ($ext[1]) {
case 'jpg':
case 'jpeg':
case 'gif':
case 'png':
break;
default:
$errors[] = array('image'=>$k, 'error'=>'Unsupported file extension.');
continue;
break;
}
}
// make a random-ish filename
$filename = time().uniqid(rand(), true) . '.' . $ext[1];
$path = '/html/uploaded/'.$filename; // upload directory path is set
move_uploaded_file($image['tmp_name'], $path); // upload the file to the server
// this is a bad idea right here! Use 775 at least, if possible
chmod($path,0777);
$files[] = array('name'=>$filename, 'path'=>$path);
}
// now loop the $files array and put the paths into the database
// you also should do something with the errors listed in $errors
EDIT
So here is a quick-and-dirty example of putting these files into the database. I note that you have a size
and ext
field - if this is supposed to record the file and extension of an image... which one? Anyway, if you fill in the other variables, the code below will put the filenames into the db.
I wanted to advise you - this database design has flaws. What if you want more than 5 images? You'd have to change the structure of the db table AND edit the code. Much better if create a relational table structure where you insert one row for each file with an ID to tie them all together (i.e. album_id
, then you have a table called albums
with top-level info in it).
// start building up the SQL query, start with
// some fields that are straightforward
$sql = '
INSERT INTO table_name (
`id`,
`status`,
`user`,
`title`,';
// now loop the list of files (5 only),
// add each needed field
for ($i=1; $i < count($files) && $i < 5; $i++) {
$sql .= '`file'.$i.'`,';
}
// build out the rest of the query, add values
// for the straightforward fields
$sql .= '
`size`,
`ext`,
`ip`,
`date`
) VALUES (
NULL,
"'.$status.'",
"'.$user.'",
"'.$title.'",
';
// loop the files
$ct = 1;
foreach ($files as $f) {
$sql .= '"'.$f['name'].'",';
// only allow 5 files
if ($ct == 5)
break;
$ct++;
}
// wrap up building the query
$sql .= '
"'.$size.'",
"'.$ext.'",
"'.$ip.'",
"'.$date.'"
)';
mysql_query($sql);
First of all, you should use apostrophes when accessing associative arrays like $_FILES in your for loop.
Concerning your problem: Why not use something like $filename = sprintf('%s%d.%s', md5(uniqid(rand(), true)), $key, $file_ext);
as replacement for $filename = md5(uniqid(rand(), true)) . '.' . $file_ext;
.
精彩评论