|
Uploading multiple files
Multiple files can be uploaded using different
It is also possible to upload multiple files simultaneously and have the information organized automatically in arrays for you. To do so, you need to use the same array submission syntax in the HTML form as you do with multiple selects and checkboxes:
Note:
Support for multiple file uploads was added in PHP 3.0.10. Example 5.4. Uploading multiple files<form action="file-upload.php" method="post" enctype="multipart/form-data">
When the above form is submitted, the arrays
For instance, assume that the filenames
Code Examples / Notes » features.file_upload.multiplehotmail.com
With multiple file uploads post_max_size: the total amount of data posted by the client (all files, and all other form field) upload_max_filesize: the maximum size of 1 single file. (just like <input type="hidden" name="MAX_FILE_SIZE" value="..."/>) so, with the directives: post_max_size 25M upload_max_filesize 2M you can send 12 files of up to 2 MB and use up to 1 MB for your additional form-values. As long as you read only a single copy of 1 file into memory, the memory_limit directive can be held reasonable small as well. phpuser
When uploading multiple files, the $_FILES variable is created in the form: Array ( [name] => Array ( [0] => foo.txt [1] => bar.txt ) [type] => Array ( [0] => text/plain [1] => text/plain ) [tmp_name] => Array ( [0] => /tmp/phpYzdqkD [1] => /tmp/phpeEwEWG ) [error] => Array ( [0] => 0 [1] => 0 ) [size] => Array ( [0] => 123 [1] => 456 ) ) I found it made for a little cleaner code if I had the uploaded files array in the form Array ( [0] => Array ( [name] => foo.txt [type] => text/plain [tmp_name] => /tmp/phpYzdqkD [error] => 0 [size] => 123 ) [1] => Array ( [name] => bar.txt [type] => text/plain [tmp_name] => /tmp/phpeEwEWG [error] => 0 [size] => 456 ) ) I wrote a quick function that would convert the $_FILES array to the cleaner (IMHO) array. <?php function reArrayFiles(&$file_post) { $file_ary = array(); $file_count = count($file_post['name']); $file_keys = array_keys($file_post); for ($i=0; $i<$file_count; $i++) { foreach ($file_keys as $key) { $file_ary[$i][$key] = $file_post[$key][$i]; } } return $file_ary; } ?> Now I can do the following: <?php if ($_FILES['upload']) { $file_ary = reArrayFiles($_FILES['ufile']); foreach ($file_ary as $file) { print 'File Name: ' . $file['name']; print 'File Type: ' . $file['type']; print 'File Size: ' . $file['size']; } } ?> sgoodman_at_nojunk_immunetolerance.org
Re: phpuser_at_gmail's comment, a simpler way to have create that data structure is to name your HTML file inputs different names. If you want to upload multiple files, use: <input type=file name=file1> <input type=file name=file2> <input type=file name=file3> etc... Each field name will be a key in the $_FILES array. 29-jul-2005 03:50
re: phpuser's comment I found that if instead of the form structure at the top of the page use one like this: <form action="file-upload.php" method="post" enctype="multipart/form-data"> Send these files:<br /> <input name="userfile1" type="file" /><br /> <input name="userfile2" type="file" /><br /> <input type="submit" value="Send files" /> </form> Notice the names are unique and not an array element. Now the array is structured more like phpuser would like. I did this and used... foreach ($_FILES as $file) { ... } without issue. andrex dot da
I've made a function to upload many files at once, you can give an array, or send an alone file. Change the array with the extensions you want. <?php // Andrés Ortiz function UploadFiles($files,$folder){ $extperms = array('gif','jpg','png'); if(is_array($files)){ for($i=0;$i<count($files['error']);$i++){ if($files['error'][$i] == 0){ $tmpname = $files['tmp_name'][$i]; $ext = strtolower(substr($files['name'][$i], -3, 3)); $filename = $files['name'][$i]; if(in_array($ext, $extperms)){ $endpath[$i] = $folder . $files['name'][$i]; if(!@move_uploaded_file($files['tmp_name'][$i], $endpath[$i])){ $logger['UploadFiles'][] = 'Couldn\'t upload the file, try again later'; } else{ if(!@chmod($endpath[$i], 0777)){ $logger['UploadFiles'][] = 'Couldn\'t change permissions file, ignoring...'; } } $weigth[$i] = ($tam = @stat($endpath[$i]))?$tam[7]:$endpath[$i]; } else{ $logger['UploadFiles'][] = 'You must upload files with image extensions (JPG, PNG, GIF)'; } } else{ $logger['UploadFiles'][] = 'The files have errors, check first and then try again'; return false; // If you don't want what the others uploads die, comment this. } } return array('files' => $endpath, 'stat' => $weigth); } else{ if($files['error'] == 0){ $tmpname = $files['tmp_name']; $ext = strtolower(substr($files['name'], -3, 3)); $filename = $files['name']; if(in_array($ext, $extperms)){ $endpath = $folder . $files['name']; if(!@move_uploaded_file($files['tmp_name'], $endpath)){ $logger['UploadFiles'][] = 'Couldn\'t upload the file, try again later'; } else{ if(!@chmod($endpath, 0777)){ $logger['UploadFiles'][] = 'Couldn\'t change permissions file, ignoring...'; } } $weigth = ($tam = @stat($endpath))?$tam[7]:$endpath[$i]; } else{ $logger['UploadFiles'][] = 'You must upload files with image extensions (JPG, PNG, GIF)'; } } else{ $logger['UploadFiles'][] = 'The files have errors, check first and then try again'; return false; } return array('files' => $endpath, 'stat' => $weigth); } if(count($logger['UploadFiles'])>0){ echo '<pre><br /> <b>Some Errors were found.</b><hr /><br />'; print_r($logger); echo '</pre>'; } } /* function [array],[Destination Folder] */ UploadFiles($_FILES,'uploads/files/'); ?> captlid
I noticed that the manual does not have a basic processing script for testing purposes to process multiple file uploads. It took me about an hour to figure this out so I figured it should help some newbie. Also on windows, the OS does not care if you use backslashes and front slashes while writing up a directory path. So for compatibility with *nix just keep it as a foward slash. (Tested with php5, php4, apache 1.3x and 2x, on winxp pro, win2k pro and win98se and freebsd.) The script is kept simple for illustration purposes. Dont use it in a production environment. The form <form method="post" action="" enctype="multipart/form-data"> <input type="hidden" name="MAX_FILE_SIZE" value="500000"> <? for($i = 1; $i <= $_POST[totalfiles]; $i++) { echo $i.'. <input type="file" name="photos[]"> '."\n"; } ?> <input type="submit" name="sendfiles" value="Send Files"></form> The processing script, for simplicities sake in the same file. if ($_POST[sendfiles]) { print_r($_POST); echo '<pre>'; print_r($_FILES); echo '</pre>'; $uploaddir = getcwd().'/photos/; //a directory inside foreach ($_FILES[photos][name] as $key => $value) { $uploadfile = $uploaddir . basename($_FILES[photos][name][$key]); //echo $uploadfile; if (move_uploaded_file($_FILES['photos']['tmp_name'][$key], $uploadfile)) { echo $value . ' uploaded '; } } } bob doe
Here is a the simple test form I needed, pieced togther from 2 or 3 posts in the documentation elsewhere. <html> <head> <title>HTML Form for uploading image to server</title> </head> <body> <form action="" method="post" enctype="multipart/form-data"> Pictures: <input type="file" name="pictures[]" /> <input type="file" name="pictures[]" /> <input type="file" name="pictures[]" /> <input type="submit" value="Send" /> </form> <?php //places files into same dir as form resides foreach ($_FILES["pictures"]["error"] as $key => $error) { if ($error == UPLOAD_ERR_OK) { echo"$error_codes[$error]"; move_uploaded_file( $_FILES["pictures"]["tmp_name"][$key], $_FILES["pictures"]["name"][$key] ) or die("Problems with upload"); } } ?> </body> </html> bishop
Elaboration on phpuser at gmail dot com reArrayFiles() function (which assumed sequential, integer keys and uni-dimensional), this function will work regardless of key and key depth: <?php // information grouper function groupFileInfoByVariable(&$top, $info, $attr) { if (is_array($info)) { foreach ($info as $var => $val) { if (is_array($val)) { groupFileInfoByVariable($top[$var], $val, $attr); } else { $top[$var][$attr] = $val; } } } else { $top[$attr] = $info; } return true; } // usage $newOrdering = array (); foreach ($_FILES as $var => $info) { foreach (array_keys($info) as $attr) { groupFileInfoByVariable($newOrdering, $info[$attr], $attr); } } // $newOrdering holds the updated order ?> |