Assuming multiple upload input types exist on a HTML page, I want to be able to obtain the name
attribute of each file upload that is submit with a file, this way the PHP server-side can determine exactly what file uploader is passing what file.
My Code:
$('.php-email-form').submit(function (event) {
event.preventDefault();
var form = $(this);
var data = new FormData();
// add datas of input not file to data object
$.each($(':input', form).not(':input[type=submit]'), function(i, fields){
data.append($(fields).attr('name'), $(fields).val());
console.log($(fields).attr('name'), $(fields).val());
});
// add data from inputs type file
$.each($('input[type=file]', form)[0].files, function (i, file) {
data.append(file.name, file);
console.log(file.name);
console.log($(this).attr('name')); // test, trying to get the name attribute of input type file
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form class="php-email-form" enctype="multipart/form-data">
<input type="text" name="test" value="value"><br>
<input type="file" class="custom-file-input" id="photo" name="photo"><br>
<input type="submit">
</form>
When I look at the $_FILES
array in PHP, I get the following output:
array(1) { ["test"]=> string(5) "value" }
array(1) { ["IMG_8085_JPG"]=> array(5) { ["name"]=> string(12) "IMG_8085.JPG" ["type"]=> string(10) "image/jpeg" ["tmp_name"]=> string(14) "/tmp/phpxsP6RN" ["error"]=> int(0) ["size"]=> int(65949) } }
As seen above, the index of the above image is the image name (IMG_8085_JPG) though I want this index to be the name of the original input it came from. (Either photo or photo-2)
So if an image was uploaded in the photo
element, the array should look like the following:
array(1) { ["test"]=> string(5) "value" }
array(1) { ["photo"]=> array(5) { ["name"]=> string(12) "IMG_8085.JPG" ["type"]=> string(10) "image/jpeg" ["tmp_name"]=> string(14) "/tmp/phpxsP6RN" ["error"]=> int(0) ["size"]=> int(65949) } }
It seems that the name
index is overwritten on the elements when a file is uploaded, so $(this).attr("name")
no longer references the attribute but rather becomes the name of the file that is uploaded.
I post all my jQuery code below :
$('.php-email-form').submit(function (event) {
event.preventDefault();
var form = $(this);
var formAction = $(form).attr('action');
var data = new FormData();
// add data from inputs type text
$.each($(':input', form).not(':input[type=submit]'), function(i, fields){
data.append($(fields).attr('name'), $(fields).val());
});
// add data from inputs type file
$.each($('input[type=file]', form)[0].files, function (i, file) {
data.append(file.name, file);
console.log(file);
console.log($(this).attr('name'));
});
$('.loading').fadeIn();
$.ajax({
url: formAction,
type: "POST",
data: data,
contentType: false,
cache: false,
processData: false,
}).done(function(data){
$('.loading').hide();
$('.sent-message').fadeIn().html(data);
}).fail(function(jqXHR, textStatus, errorThrown) {
$('.loading').hide();
$('.error-message').show().html(errorThrown);
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
The result i expect when i var_dump $_POST & $_FILES :
array(1) { ["test"]=> string(5) "value" }
array(1) { ["photo"]=> array(5) { ["name"]=> string(12) "IMG_8085.JPG" ["type"]=> string(10) "image/jpeg" ["tmp_name"]=> string(14) "/tmp/phpxsP6RN" ["error"]=> int(0) ["size"]=> int(65949) } }
2
Answers
You are iterating through each input’s file directly instead of the element itself, this makes the type attribute accessible.
The difference here is that when you are iterating through
('input[type=file]', form)[0].files
, you are accessing the files directly and the parent input that they are coming from aren’t accessible because there is no reference to them.The solution is to iterate through every input with the type of ‘file’ so we still fetch every input and have access to the ‘name’ attribute, we can then fetch the file itself that was uploaded within the loop with
this.files[0]
. (Gets the first file uploaded.)The main thing missing in the code is
enctype
attribute for the form. Whenever you use a file input in a form, you must specify the enctype asmultipart/form-data
.Change your form tag to:
Now you can send the form as simple as (no need to assign values manually)
and echo the $_FILES from the test-dest.php using
This will give you the result in