i like to upload some images to a directory with the help of arrays. therefore i have this code:
$allowedExtensions = array('jpg', 'jpeg', 'png', 'bmp', 'tiff', 'gif');
$maxSize = 2097152;
$Dir = "a/b/c/d";
$storageDir = "a/b/c/d/tmp_images";
//Arrays
$errors2 = $output = array();
if(!empty($_FILES['image'])){
// Validation loop (I prefer for loops for this specific task)
for ($i = 0; isset($_FILES['image']['name'][$i]); $i++) {
$fileName = $_FILES['image']['name'][$i];
$fileSize = $_FILES['image']['size'][$i];
/*$fileErr = $_FILES['image']['error'][$i];*/
$fileExt = strtolower(pathinfo($fileName, PATHINFO_EXTENSION));
// Dateiendung überprüfen
if (!in_array($fileExt, $allowedExtensions)) {
$errors2[$fileName][] = "format $fileExt in $fileName is not accepted";
}
// check filesize
if ($fileSize > $maxSize) {
$errors2[$fileName][] = "maxsize of 2MB exceeded";
}
}
/*// Handle validation errors here
if (count($errors) > 0) {
echo "Fehler beim Upload des Bildmaterials:";
echo ($errors); ->gibt "Array" aus
}*/
if (is_dir($Dir)){
mkdir($storageDir, 0755);
}else{
mkdir($Dir, 0755);
mkdir($storageDir, 0755);
}
// Fileupload
for ($i = 0; isset($_FILES['image']['name'][$i]); $i++) {
// Get base info
$fileBase = basename($_FILES['image']['name'][$i]);
$fileName = pathinfo($fileBase, PATHINFO_FILENAME);
$fileExt = pathinfo($fileBase, PATHINFO_EXTENSION);
$fileTmp = $_FILES['image']['tmp_name'][$i];
// Construct destination path
$fileDst = $storageDir.'/'.basename($_FILES['image']['name'][$i]);
for ($j = 0; file_exists($fileDst); $j++) {
$fileDst = "$storageDir/$fileName-$j.$fileExt";
}
// Move the file
if (count($errors2) == 0) {
if (move_uploaded_file($fileTmp, $fileDst)) {
...
}
}
the problem with that code is the following: in case of uploading two or more files with an accepted ending it will echo out:
Warning: move_uploaded_file() [function.move-uploaded-file]: Unable to access abc2.png in /a/b/xxx.php on line xxx
which refers to that line:
if (move_uploaded_file($fileTmp, $fileDst)) {
this message will be shown for each picture except the first one. so i have no clue what i do wrong. i would really appreciate if there is someone who could help me out. i really would appreciate. thanks a lot.
First of, I would name the uploaded fields seperatly. E.g. name the first field <input name="image_1" type="file" /> and the second <input name="image_2" type="file" />. Then you can iterate over the $_FILES array instead:
foreach($_FILES as $fileId => $file){
//make sure it's a file you want (optional)
if(!preg_match("/^image\_\d+$/",$fileId){
continue;
}
//the rest of your code from the for loop
}
Secondly, you need to make sure that your form's enctype is multipart/form-data.
Does any of this help?
Your code is very similar to my answer at limiting the checking condition while uploading swf files
This is how you should implement such ..
FULL Script
<?php
error_reporting ( E_ALL );
$allowedExtensions = array (
'jpg',
'jpeg',
'png',
'bmp',
'tiff',
'gif'
);
$maxSize = 2097152;
$dirImage = "photos/tmp_images";
$errors = $output = array ();
if (isset ( $_FILES ['image'] )) {
foreach ( $_FILES ['image'] ['tmp_name'] as $key => $val ) {
$fileName = $_FILES ['image'] ['name'] [$key];
$fileSize = $_FILES ['image'] ['size'] [$key];
$fileTemp = $_FILES ['image'] ['tmp_name'] [$key];
$fileExt = pathinfo ( $fileName, PATHINFO_EXTENSION );
$fileExt = strtolower ( $fileExt );
if (empty ( $fileName ))
continue;
// Dateiendung überprüfen
if (! in_array ( $fileExt, $allowedExtensions )) {
$errors [$fileName] [] = "format $fileExt in $fileName is not accepted";
}
if ($fileSize > $maxSize) {
$errors [$fileName] [] = "maxsize of 2MB exceeded";
}
if (! mkdir_recursive ( $dirImage, 0777 )) {
$errors [$fileName] [] = "Error Creating /Writing Directory $dirImage ";
}
// Construct destination path
$fileDst = $dirImage . DIRECTORY_SEPARATOR . $fileName;
$filePrifix = basename ( $fileName, "." . $fileExt );
$i = 0;
while ( file_exists ( $fileDst ) ) {
$i ++;
$fileDst = $dirImage . DIRECTORY_SEPARATOR . $filePrifix . "_" . $i . "." . $fileExt;
}
// Move the file
if (count ( $errors ) == 0) {
if (move_uploaded_file ( $fileTemp, $fileDst )) {
// ...
$output [$fileName] = "OK";
}
}
}
}
function mkdir_recursive($pathname, $mode) {
is_dir ( dirname ( $pathname ) ) || mkdir_recursive ( dirname ( $pathname ), $mode );
return is_dir ( $pathname ) || mkdir ( $pathname, $mode );
}
if (! empty ( $errors )) {
echo "<pre>";
foreach ( $errors as $file => $error ) {
echo $file, PHP_EOL;
echo "==============", PHP_EOL;
foreach ( $error as $line ) {
echo $line, PHP_EOL;
}
echo PHP_EOL;
}
echo "</pre>";
}
if (! empty ( $output )) {
echo "<pre>";
echo "Uploaded Files", PHP_EOL;
foreach ( $output as $file => $status ) {
echo $file, "=", $status, PHP_EOL;
}
echo "</pre>";
}
?>
<form method="post" enctype="multipart/form-data">
<label for="file">Filename 1:</label> <input type="file" name="image[]"
id="file" /> <br /> <label for="file">Filename 2:</label> <input
type="file" name="image[]" id="file" /> <br /> <label for="file">Filename
3:</label> <input type="file" name="image[]" id="file" /> <br /> <input
type="submit" name="submit" value="Submit" />
</form>
Why are you accessing the $_FILES superglobal array as a three dimensional array?
if you want the file name of the file uploaded from an <input type="file" name="image"/> all you have to do is $name = $_FILES[ 'image' ][ 'name' ] there is no need for the [ $i ] at the end.
You need to loop over the entries in $_FILES like this:
foreach ( $_FILES as $inputName => $fileData )
{
// $inputName is be 'image` for the first input and so on,
// $fileData will be an array of the attributes [ 'name', 'tmp_name', ... ]
}
I'm not sure if this may solve it for you, but you can try to convert these into "normal" $_FILES values.
$arr_files = #$_FILES['image'];
$_FILES = array();
foreach(array_keys($arr_files['name']) as $h)
$_FILES["image_{$h}"] = array( 'name' => $arr_files['name'][$h],
'type' => $arr_files['type'][$h],
'tmp_name' => $arr_files['tmp_name'][$h],
'error' => $arr_files['error'][$h],
'size' => $arr_files['size'][$h]);
And then run the loop like normal.
See previous related answer
Related
controller:
if($_POST)
{
$filename = $_FILES['file']['name'];
$temp = explode(".", $filename);
$newfilename = round(microtime(true)) . '.' . end($temp);
$ext = pathinfo($filename, PATHINFO_EXTENSION);
$array = array("jpg","jpeg","png");
$PATH = "public/images/users/";
if(in_array($ext,$array)){
if(move_uploaded_file($_FILES['file']['tmp_name'], $PATH.$newfilename)){
$data = array(
"name" => $this->input->post('name'),
"image_gallery" => $newfilename
);
$insert = $this->db->insert('product',$data);
}else{
echo $this->lang->line('notUpload');
}
}else{
echo $this->lang->line('extNotMatch');
}
}
view:
<?php echo $this->session->flashdata('success'); ?>
<form method="post" enctype="multipart/form-data">
<div class="card m-0">
<div class="card-body">
<input type="text" class="form-control" id="name" name="name" placeholder="Name">
<input type="file" id="files" name="files[]" multiple/>
<button type="submit" id="submit" name="submit" class="btn btn-primary">Submit</button>
</div>
</div>
</form>
In this code I have simply create a form and want to insert form data along with multiple images but I have got an error
Message: explode() expects parameter 2 to be string, array given
and
Message: pathinfo() expects parameter 1 to be string, array given
and I also want to change name of uploaded image. So, How can I do this? Please help me.
Thank You
Modify your controller code as below:
if($_POST)
{
$total = count($_FILES['files']['name']);
for( $i=0 ; $i < $total ; $i++ ) {
$filename = $_FILES['files']['name'][$i];
$temp = explode(".", $filename);
$newfilename = round(microtime(true)) . '.' . end($temp);
$ext = pathinfo($filename, PATHINFO_EXTENSION);
$array = array("jpg","jpeg","png");
$PATH = "public/images/users/";
if(in_array($ext,$array)){
if(move_uploaded_file($_FILES['files']['tmp_name'][$i], $PATH.$newfilename)){
$data = array(
"name" => $this->input->post('name'),
"image_gallery" => $newfilename
);
$insert = $this->db->insert('product',$data);
}else{
echo $this->lang->line('notUpload');
}
}else{
echo $this->lang->line('extNotMatch');
}
}
}
explode will take a string and use the delimiter argument to split into pieces. In the original, because you are using multiple to allow multiple files $_FILES['file']['name'] becomes an array in it's own right. The same issue affected the pathinfo call so you need to use a different syntax to access the file data. If you create the variables at the beginning of the loop you can avoid such issues.
if( $_SERVER['REQUEST_METHOD']=='POST' && !empty( $_FILES[ $fieldname ] ) ){
$errors=array();
$allowed=array( "jpg", "jpeg", "png" );
$path='public/images/users/';
$fullpath=__DIR__ . '/' . $path;
$fieldname='file';
# multiple files require a slightly odd syntax to access each file
foreach( $_FILES[ $fieldname ]['name'] as $i => $void ) {
if( !empty( $_FILES[ $fieldname ]['tmp_name'][$i] ) ) {
$name = $_FILES[ $fieldname ]['name'][$i];
$size = $_FILES[ $fieldname ]['size'][$i];
$type = $_FILES[ $fieldname ]['type'][$i];
$tmp = $_FILES[ $fieldname ]['tmp_name'][$i];
$error= $_FILES[ $fieldname ]['error'][$i];
$ext = pathinfo( $name, PATHINFO_EXTENSION );
list( $width, $height, $type, $attr ) = getimagesize( $tmp );
/*
other tests - check mime type? size?
*/
if( in_array( $ext, $allowed ) ){
/*
using the full path rather than a relative path
is, in my opinion, more reliable - hence __DIR__
*/
$filename=sprintf('%s.%s',round(microtime(true)),$ext);
$filepath=sprintf('%s%s',$fullpath,$filename);
$displaypath=sprintf('%s%s',$path,$filename);
$status=move_uploaded_file( $tmp, $filepath );
if( $status ){
$data=[
'name' => $this->input->post('name'),
'image_gallery' => $displaypath
];
$insert = $this->db->insert('product',$data);
}else{
$errors[$name][]=$this->lang->line('notUpload');
}
}else{
$errors[$name][]=$this->lang->line('extNotMatch');
}
}
}
if( !empty( $errors ) ){
foreach($errors as $name => $arr){
printf('<h1>%s</h1><pre>%s</pre>',$name,print_r($arr,true));
}
}
}
I have two form submitting buttons in one form, and I want to use $uploaded array in elseif() {...} like this $data ['pic_path'] = $uploaded;, but it doesn't work. I can only print out $uploaded inside of if () {...}, or inside the html body. What should I do to save the $uploaded in $data array? Thanks!
Here's the code:
<?php
if (isset($_POST[submit_image])) {
if (!empty($_FILES["files"]["name"][0])) {
$files = $_FILES["files"];
//arrarys to include files uploaded successfully and failed
$uploaded = array();
$failed = array();
//access tmp_name arrary
foreach ($files['name'] as $position => $file_name) {
$file_tmp = $files["tmp_name"][$position];
$file_ext = explode(".", $file_name);
$file_ext = strtolower(end($file_ext));
$file_name_new = uniqid("", true) . "." . $file_ext;
$file_destination = "uploads/" . $file_name_new;
if (move_uploaded_file($file_tmp, $file_destination)) {
$uploaded[$position] = $file_destination;
} else {
$failed[$position] = "error";
}
}
print_r($uploaded);
}
} elseif (isset($_POST[submit_post])) {
$data = array();
$data['comments'] = $_POST['comments'];
//$data ['pic_path'] = $uploaded;
//print_r($uploaded);
}
?>
<!DOCTYPE html>
<head>
</head>
<body>
<form method="post" enctype="multipart/form-data">
<input type="file" name="files[]" multiple />
<input type="submit" name="submit_image"/>
<textarea name="comments"></textarea>
<button type="submit" name="submit_post">Submit Your Post</button>
</form>
</body>
</html>
That's because $uploaded only exists in the if statement you declared it in. You will need to loop through files again in the elseif or move your declaration of $uploaded and $failed as well as the for loop that populates them out of that if block so the variables are accessible in both paths.
Edit - Try this:
if (!empty($_FILES["files"]["name"][0]) ) {
$files = $_FILES["files"];
//arrarys to include files uploaded successfully and failed
$uploaded = array();
$failed = array();
//access tmp_name arrary
foreach ($files['name'] as $position => $file_name) {
$file_tmp = $files["tmp_name"][$position];
$file_ext = explode(".", $file_name);
$file_ext = strtolower(end($file_ext));
$file_name_new = uniqid("", true) . "." . $file_ext;
$file_destination = "uploads/" . $file_name_new;
if (move_uploaded_file($file_tmp, $file_destination)) {
$uploaded[$position] = $file_destination;
} else {
$failed[$position] = "error";
}
}
print_r($uploaded);
}
if (isset($_POST[submit_post])) {
$data = array();
$data['comments'] = $_POST['comments'];
$data ['pic_path'] = $uploaded;
}
I am trying to figure out why i am getting a bunch of errors when trying to upload multiple images
the input is <input type='file' name='file[]' multiple>
the check is:
if (!empty($_FILES['file'])){
if ($_FILES['file']['name'] != "") {
$count = 0;
foreach ($_FILES['file']['name'] as $filename) {
$allowed = array('jpg', 'jpeg', 'png', 'bmp', 'tiff', 'gif');
$img_name = $filename;
$img_extn = strtolower(end(explode('.', $img_name)));
$img_temp = $_FILES['file']['tmp_name'][$count];
$count = $count + 1;
if(in_array($img_extn, $allowed) === true){
$img_path = 'images/images/' . substr(md5(time()), 0, 10) . '.' . $img_extn;
move_uploaded_file($img_temp, $img_path);
$images = array(
'images' => $img_path,
'post_id' => $_POST['id']
);
add_images($images);
}else{
$errors[] = ''.$filename.' - file type is not allowed. Only: ' . implode(', ', $allowed) . '';
}
}
}
}
only one image is being uploaded to the temp folder
and how can i connect the post_id to the database?
Why don't you use $filename inside the foreach instead of $_FILES['file']['name']?
$img_name = $_FILES['file']['name'];
should be
$img_name = $filename;
since you are using for-each
foreach ($_FILES['file']['name'] as $filename) {
}
Multiple images. it has to be $_FILES['file']['name'][0]
Use indexes to access it. Since I see that you haven't used indexes. explode() throws a warning because it's trying to break an array.
I have this in my form:
<input type="file" name="images[]" multiple="multiple" />
then this PHP on the action page for the form:
$files = array();
$fdata = $_FILES["images"];
if(is_array($fdata["name"]))
{
//This is the problem
for ($i = 0; $i < count($fdata['name']); ++$i)
{
$files[] = array(
'name' => $fdata['name'][$i],
'tmp_name' => $fdata['tmp_name'][$i],
);
}
}
else
{
$files[] = $fdata;
}
foreach ($files as $file)
{
move_uploaded_file ( "$pic1_name","$image1") or die("image 1 did not copy<br>");
}
but i know i have the move_uploaded_file line wrong. what do i need to put in here instead?
UPDATE:
my latest code is as follows:
$files = array();
$fdata = $_FILES["images"];
if(is_array($fdata["name"]))
{
//This is the problem
for ($i = 0; $i < count($fdata['name']); ++$i)
{
$files[] = array(
'name' => $fdata['name'][$i],
'tmp_name' => $fdata['tmp_name'][$i],
);
}
}
else
{
$files[] = $fdata;
}
foreach($_FILES['images'] as $file)
{
echo $file['tmp_name'];
move_uploaded_file($file['tmp_name'], $_SERVER["DOCUMENT_ROOT"].'/img/project-gallery/test');
}
I would try something like this...of course add in some validation to make sure users are uploading only file-types which you expect
$currentDate = microtime();
$storeFolder = $_SERVER["DOCUMENT_ROOT"] . "/yourSavePath/";
$fileNames = array();
foreach ($_FILES['images']['name'] as $key => $value) {
if (!empty($_FILES['images'])) {
//tempfile is the file which has actually been stored on your server
$tempFile = $_FILES['images']['tmp_name'][$key];
//prepend the time so to make filenames unique...the filename here is the one the user sees and the temp filename above is one generated by the server
$targetFile1 = $currentDate . $_FILES['images']['name'][$key];
//get rid of spaces in the name since they can cause issues
$targetFile1 = str_replace(' ', '_', $targetFile1);
$res = move_uploaded_file($tempFile, $storeFolder . $targetFile1);
$fileNames[] = $targetFile1;
}
}
I am trying to retrieve a name of the file uploaded and append it into .list. The problem is that the file name it is retrieving from the $_SESSION variable is always the last file updated and then it doesn't change.
For example if I upload these files below in the server:
desert.jpg
tulips.jpg
lighthouse.jpg
desert_2.jpg
Then the file names it should append from $_SESSION should be:
desert.jpg
tulips.jpg
lighthouse.jpg
desert_2.jpg
But instead it is appending this below for file names retrieved from $_SESSION on screen:
desert.jpg
desert.jpg
desert.jpg
desert.jpg
How can it be fixed so that when a file is uploaded onto the server, it's file name is appended onto .list?
Below is the javascript function where $_SESSION variable is in the json code which displays the name of the file on the screen by appending it onto .list:
function stopImageUpload(success){
var imagename = <?php echo json_encode(isset($_SESSION ['fileImage']['name']) ? $_SESSION ['fileImage']['name'] : null); ?>;
if (success == 1){
$('.listImage').append(imagename + '<br/>');
}
else {
$('.listImage').append('No File');
}
return true;
}
Below is the php code where it uploads the file:
<?php
session_start();
$result = 0;
$errors = array ();
$dirImage = "ImageFiles/";
$allowedTypes = array (
"image/jpeg",
"image/gif",
"image/pjpeg",
"image/jpg",
"image/png",
"image/tif"
);
if (isset ( $_FILES ['fileImage'] ) && $_FILES ["fileImage"] ["error"] == UPLOAD_ERR_OK) {
$fileName = $_FILES ['fileImage'] ['name'];
$fileSize = $_FILES ['fileImage'] ['size'];
$fileTemp = $_FILES ['fileImage'] ['tmp_name'];
$fileType = $_FILES ['fileImage'] ['type'];
$fileExt = pathinfo ( $fileName, PATHINFO_EXTENSION );
$fileExt = strtolower ( $fileExt );
if (empty ( $fileName ))
continue;
if (! in_array ( $fileType, $allowedTypes )) {
$errors [] = "File Type is not accepted";
}
if(!is_writable($dirImage ))
{
$errors [] = "File Destination not writeable";
}
$fileDst = $dirImage . DIRECTORY_SEPARATOR . $fileName;
$filePrifix = basename ( $fileName, "." . $fileExt );
$i = 0;
while ( file_exists ( $fileDst ) ) {
$i ++;
$fileDst = $dirImage . DIRECTORY_SEPARATOR . $filePrifix . "_" . $i . "." . $fileExt;
}
// Move the file
if (count ( $errors ) == 0) {
if (move_uploaded_file ( $fileTemp, $fileDst )) {
$result = 1;
}
}
}
$_SESSION ['fileImage'][] = $_FILES ['fileImage']['name'];
?>
<script language="javascript" type="text/javascript">window.top.stopImageUpload(<?php echo $result;?>);</script>
On seperate page I have a JSON which retrieves the $_SESSION:
function stopImageUpload(success){
var imagename = <?php echo json_encode(isset($_SESSION ['fileImage']) ? $_SESSION ['fileImage'] : null); ?>;
if (success == 1){
$('.listImage').append(imagename + '<br/>');
}
else {
$('.listImage').append('<br/>');
}
return true;
}
$_SESSION ['fileImage'][] = $_FILES ['fileImage']['name']; instead of $_SESSION ['fileImage']['name'] = $_FILES ['fileImage']['name'];