Forum Moderators: open

Message Too Old, No Replies

Upload Multiple Files From Table Form

         

SeanF

1:45 pm on Nov 12, 2022 (gmt 0)

5+ Year Member Top Contributors Of The Month



Hi:
I am trying to create a table which will allow a user to upload multiple images from a single table. The work flow would be similar to this:
    - The user is presented with a table with multiple rows
    - Each row would include a couple of text fields and a field where they can upload an image
    - At the bottom of the table is a submit button that uploads all pictures and enters the data into a database

I have found the following code which works great for a single image:
<p><input type="file" accept="image/*" name="image" id="file" onchange="loadFile(event)" style="display: none;"></p>
<p><label for="file" style="cursor: pointer;">Upload Image</label></p>
<p><img id="output" width="200" /></p>
<script>
var loadFile = function(event) {
var image = document.getElementById('output');
image.src = URL.createObjectURL(event.target.files[0]);
};
</script>

and I am trying to adapt it to work within rows of a table. What I have is:
echo "<table>";
$i = 1;
while ($i <= 3):
echo "<tr>
<td>Image $i</td>
<td><input type='file' accept='image/*' name='image$i' id='file$i' onchange='loadFile(event)' style='display: none;'></td>
<td><label for='file' style='cursor: pointer;'>Upload Image $i</label></td>
<td><img id='output$i' width='200' /></td>
</tr>";
$i++;
endwhile;
echo "</table>";

echo "<script>
var loadFile = function(event) {
var image = document.getElementById('output$i');
image.src = URL.createObjectURL(event.target.files[0]);
};
</script>
";

Clicking "Upload Image" successfully opens the select image window but the image is not returned to the image field.
What am I overlooking?

Thanks

csdude55

6:30 pm on Nov 12, 2022 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



I'm taking a guess here, but I think that using output$i in the script would mean that the script would have to be within the loop. Otherwise, "image" will always equal "output1".

Maybe something like this would work?

echo <<<EOF
<script>
var loadFile = function(event, i) {
var image = document.getElementById('output' + i);
image.src = URL.createObjectURL(event.target.files[0]);

// if it's still not working, use this to see what's coming through loadfile
console.log(image.src);
};
</script>

<table>

EOF;

for ($i=1; $i <= 3; $i++) {
echo <<<EOF
<tr>
<td>Image $i</td>
<td><input type='file' accept='image/*' name='image$i' id='file$i' onchange='loadFile(event, $i)' style='display: none;'></td>
<td><label for='file' style='cursor: pointer;'>Upload Image $i</label></td>
<td><img id='output$i' width='200' /></td>
</tr>

EOF;
}

echo "</table>";

SeanF

11:13 pm on Nov 12, 2022 (gmt 0)

5+ Year Member Top Contributors Of The Month



Thank so much for the reply!

I think I have pretty much what you have but I've removed the table structure to simplify and added a couple of things for troubleshooting
<?php
for ($i=1; $i <= 3; $i++) {
echo <<< EOF
<p><input type="file" accept="image/*" name="image" id="file" onchange="loadFile(event, $i)" style="display: none;"></p>
<p><label for="file" style="cursor: pointer;">Upload Image $i</label></p>
<p>output$i<img id="output$i" width="200" /></p>
EOF;
}
echo <<< EOF
<script>
var loadFile = function(event, i) {
console.log('No.', i);
var image = document.getElementById('output'+i);
image.src = URL.createObjectURL(event.target.files[0]);
console.log(image.src);
};
</script>
EOF;
?>

The script seems to work but the problem is that regardless of what line is clicked (1, 2 or 3) the image is always placed in "output1"
Adding a console.log to trace $i, it appears that $i is always passed as "1". The following console log is the result of clicking "Upload Image 3". Notice that "console.log('No.', i);" is showing "1"
No. 1 test_pic_upload-01a.php:12
blob:http://localhost/aa2d6b10-7ff5-44a3-ad27-2eb063bf8fef

Thoughts?

Thanks again!

csdude55

1:28 am on Nov 13, 2022 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Based on this:
[developer.mozilla.org...]

what happens if you change the script to:

<script>
function loadFile(event, i) {
console.log('No.', i);

var image = document.getElementById('output'+i);
image.src = URL.createObjectURL(this.files);

console.log(image.src);
};
</script>

SeanF

11:52 am on Nov 13, 2022 (gmt 0)

5+ Year Member Top Contributors Of The Month



"i" is still passed to the JS as "1" regardless of which line is clicked.

If I hard code "+3" in place of "+i" in the following line, the image is placed in the appropriate location.
var image = document.getElementById('output'+3);

Also, if I look as the page source, "i" is appropriately set in the script calls:
<p><input type="file" accept="image/*" name="image" id="file" onchange="loadFile(event, 1)" style="display: none;"></p>
<p><label for="file" style="cursor: pointer;">Upload Image 1</label></p>
<p>output1<img id="output1" width="200" /></p>
<p><input type="file" accept="image/*" name="image" id="file" onchange="loadFile(event, 2)" style="display: none;"></p>
<p><label for="file" style="cursor: pointer;">Upload Image 2</label></p>
<p>output2<img id="output2" width="200" /></p>
<p><input type="file" accept="image/*" name="image" id="file" onchange="loadFile(event, 3)" style="display: none;"></p>
<p><label for="file" style="cursor: pointer;">Upload Image 3</label></p>
<p>output3<img id="output3" width="200" /></p>

<script type='text/javascript'>
var loadFile = function(event, i) {
console.log('No.', i);
var image = document.getElementById('output'+i);
image.src = URL.createObjectURL(event.target.files[0]);
console.log(image.src);
};
</script>

I think the only problem is that "i" is not being passed successfully. Seems trivial, but I don't see where the problem is.

Otherwise, the console log is:
No. 1
test_pic_upload-01a.php:12
Uncaught TypeError: Failed to execute 'createObjectURL' on 'URL': Overload resolution failed.
at loadFile (test_pic_upload-01a.php:12:18)
at HTMLInputElement.onchange (test_pic_upload-01a.php:1:118)
loadFile @ test_pic_upload-01a.php:12
onchange @ test_pic_upload-01a.php:1

SeanF

3:23 pm on Nov 13, 2022 (gmt 0)

5+ Year Member Top Contributors Of The Month



I found the problem but I can't explain why...

If I remove the "style='display: none;'" parameter and use the button which is displayed, it works just as expected.

Not sure what's causing that but i'll continue to investigate... or I'll just settle for having the button

robzilla

4:59 pm on Nov 13, 2022 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



If your input fields have an ID like file$i, e.g. file1 or file2, you should also put that ID in the "for" attribute of the accompanying <label> element. Right now it's <label for="file"> everywhere.

csdude55

8:07 pm on Nov 13, 2022 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



That's a good point, I didn't catch that before. Your ID field has to be unique, so that could be the source of your woes here.

I can't really duplicate the issue on JSFiddle without removing the display style, how do you trigger the onChange?

Or if you're tired of dealing with it, you might be able to use style="visibility: hidden; width: 0; height: 0" to get the same affect as "display: none".