Let's go through this step by step:
1:
I added [] because I have multiple row that requires more image to be uploaded for each row.
Ok, to upload multiple files in one call, you need to add the multiple
keyword to your input element. Also making your element readonly
seems somewhat at odds with uploading files.....
<td><input type="file" class="form-control total" name="myfile[]" multiple></td>
2:
The error you report states:
Warning: end() expects parameter 1 to be array, string given in ... on line 39
Which is pretty clear; you're passing it a string when it expects an array. This is obvious from the typo on line 38:
$f_extension = implode('.',$f_name);
Your line here is taking an array of values ($f_name
) and compacting them into a string
As you can see from the error, the end
function expects an array, not a string.
The solution to this is to stop imploding. As commented by Nigel you almost certainly are looking for explode not implode.
explode
breaks a string into an array of parts. implode
does the exact opposite.
3:
You further reference in your comment:
when i use explode, it returns this Warning: explode() expects parameter 2 to be string, array given
This is the crux of your issue and is because you are defining a multiple file upload rather than a single file.
As outlined in more detail here, when uploading files via PHP there are two structure layouts, one for single files and one for multiple sets of files.
You are coding as if you're using single files, but the data being given to PHP from the upload process is actually for multiple files, here is an example of the difference:
Single file:
$_FILES['myfile']['name'] = 'filename';
$_FILES['myfile']['tmp_name'] = '/some/temp/server/addres';
$_FILES['myfile']['size'] = 345;
$_FILES['myfile']['error'] = 0;
$_FILES['myfile']['type'] = 'file/mimetype';
multiple files:
Uploads marked as Multiple
always have the same structure regardless of if they're uploading 1 or 10 files. The elements will always be numeric arrays rather than strings.
// Each of these values are now numerical arrays, one for each file.
$_FILES['myfile']['name'][0] = 'filename_1';
$_FILES['myfile']['name'][1] = 'filename_2.css';
$_FILES['myfile']['tmp_name'][0] = '/some/temp/server/address_1';
$_FILES['myfile']['tmp_name'][1] = '/some/temp/server/address_2';
$_FILES['myfile']['size'][0] = 345;
$_FILES['myfile']['size'][1] = 678;
$_FILES['myfile']['error'][0] = 0;
$_FILES['myfile']['error'][1] = 0;
$_FILES['myfile']['type'][0] = 'file/mimetype';
$_FILES['myfile']['type'][1] = 'text/css';
So you should be able to see the difference, you are treating the $f_name
as if it is a string when it is actually an array of all name values of all uploaded files.
$f_name = [
$_FILES['myfile']['name'][0],
$_FILES['myfile']['name'][1],
$_FILES['myfile']['name'][2]
];
Therefore, $f_extension
returns an error when you explode
it into an array because its subject is already an array.
Here is some further information about Multiple File Uploads, as well as the PHP Manual documentation.
4: How to fix this
I could show you how to fix this issue, but really, you should NEVER EVER TRUST USER DATA, so you must never trust the file extension set in the name
key, or the mime type.
Instead you should read this Stack Overflow question and have your server independently check the mime type of the file that's been uploaded and then set an appropriate extenstion string.
Typically you should use FileInfo to check the expected file type and use a switch
statement to then find the correct extension, such as (rough example):
$finfo = finfo_open(FILEINFO_MIME_TYPE); // return mime type extension
// For a single file
$mimeType = finfo_file($finfo, $_FILES['myfile']['tmp_name']);
// OR
// For a multiple file in a loop ($i)
$mimeType = finfo_file($finfo, $_FILES['myfile']['tmp_name'][$i]);
// The above will return some form of mime type, check this format to set the extension:
$extension = "";
switch($mimeType){
case "image/jpeg":
$extension = ".jpeg";
break;
case "image/gif":
$extension = ".gif";
break;
case "image/png":
$extension = ".png";
break;
default:
$error = "BAD! Invalid file MIME Type";
// do something here. Feed error back to user.
}
finfo_close($finfo);
P.s Useful list of common mime types