Support for Drupal 7 is ending on 5 January 2025—it’s time to migrate to Drupal 10! Learn about the many benefits of Drupal 10 and find migration tools in our resource center.
With a form of the following type (assmuming enctype is set correctly):
$form['foo'] = array(
'#type' => 'fieldset',
'#title' => 'foo',
'#tree' => TRUE,
);
$form['foo']['bar'] = array(
'#type' => 'file',
'#title' => 'bar',
}
There is no way to use form_check_upload or file_save_upload as those functions only check $_FILES['edit']['name'][$source] but the form will generate $_FILES['edit']['name']['foo']['bar'].
Comment | File | Size | Author |
---|---|---|---|
#18 | drupal-6.15-tree-file-fix-cvs-2.patch | 5.08 KB | Dmitriy.trt |
#14 | drupal-6.15-tree-file-fix-cvs.patch | 4.97 KB | Dmitriy.trt |
#13 | drupal-6.15-tree-file-fix-cvs.patch | 4.97 KB | Dmitriy.trt |
#11 | drupal-6.15-tree-file-fix.patch | 4.49 KB | Dmitriy.trt |
Comments
Comment #1
magico CreditAttribution: magico commentedAnyone else had this problem? Need confirmation, because it seems strange to the presence of this bug.
Thanks.
Comment #2
mr700 CreditAttribution: mr700 commentedI can confirm this, had to use flat fieldset for files.
Comment #3
jcastr1 CreditAttribution: jcastr1 commentedI also had this problem. I had to use markup tags in the form to display fields in a fieldset.
explained here http://drupal.org/node/83506
Comment #4
mikeryanThis issue remains in Drupal 6 - is there a reason not to support file_save_upload() in forms with #tree=TRUE, other than no one has offered a patch yet?
Thanks.
Comment #5
mikeryanActually, never mind... Looking closer at how $_FILES is arranged I see that it does work, you just have to pass the fieldset name in $source.
Thanks.
Comment #6
mistresskim CreditAttribution: mistresskim commentedCan anyone confirm this is working for them? And if so, how they specified the $source parameter in file_save_upload(). I have a form with two upload fields as follows:
$form['photos']['photo01'] = array(
'#type' => 'file',
'#title' => t('Photo 1'),
);
$form['photo02'] = array(
'#type' => 'file',
'#title' => t('Photo 2'),
);
I put the second in just to make sure the form was okay.
$file = file_save_upload('photo01', $validators, $dest, FALSE) produces a $file object with just "0" but
$file = file_save_upload('photo02', $validators, $dest, FALSE) works fine.
Yet in system.admin.inc, which has an upload field for the site logo in a fieldset, $file = file_save_upload('logo_upload', array('file_validate_is_image' => array())) also works.
Is there something else I need to declare so the function knows the field name is inside a fieldset?
Comment #7
ainigma32 CreditAttribution: ainigma32 commentedLike mikeryan said; if you use a file field inside a field setting you use the fieldset name in stead of the file field name.
So in your case that would mean
$file = file_save_upload('photos', $validators, $dest, FALSE)
would get you photo1.You will run into problems if you try to use more than one file field inside a fieldset. In that case the last file field is returned.
- Arie
Comment #9
hanoiiI just got here while porting a module which uses a file field inside a fieldset with #tree set to true. Not sure if this issue should be closed.
- What happens if we have more than one file field inside a fieldset with #tree set to true? Probably it won't work, thus it's a bug, unless it's a known issue, which should be documented somewhere in the API, but at least leaving it open leaves some probability of looking into this issue.
Comment #10
kirikintha CreditAttribution: kirikintha commentedThis is a Q&D on how we did it with system_settings_form on Drupal 6.12
In ours we did this with our fieldset:
Comment #11
Dmitriy.trt CreditAttribution: Dmitriy.trt commentedPatch was made from Drupal 6.15, it adds support for #tree and file form elements inside tree. You can use it just like you set error in validation function for elements inside tree:
I don't think it can break additional modules, because before it files with #tree didn't work at all.
Comment #13
Dmitriy.trt CreditAttribution: Dmitriy.trt commentedNew patch, made from CVS checkout of DRUPAL-6
Comment #14
Dmitriy.trt CreditAttribution: Dmitriy.trt commentedSorry, didn't change status...
Comment #16
Dmitriy.trt CreditAttribution: Dmitriy.trt commentedComment #17
Dmitriy.trt CreditAttribution: Dmitriy.trt commented#14: drupal-6.15-tree-file-fix-cvs.patch queued for re-testing.
Comment #18
Dmitriy.trt CreditAttribution: Dmitriy.trt commentedNew patch, fixed bug with filename
Comment #19
Albert Volkman CreditAttribution: Albert Volkman commentedSubscribing
Comment #20
Dmitriy.trt CreditAttribution: Dmitriy.trt commentedDoes anyone know what is wrong with testing? Patch has status "Test request sent" since 02/26/2010 !!!
Comment #21
kenorb CreditAttribution: kenorb commentedMarked #582750: Unable to upload files with 'file' form field, Ajax and AHAH helper modules as duplicate.
Comment #22
broonI encountered the same problem.
I wrote a module for a client which defines a new custom content type (due to various reasons CCK is not suitable). This content type also includes a number of images which (for workflow reasons) are contained in a fieldset named 'images'. When adding multiple images (user may add additional images by clicking AHAH button 'add another image') Drupal only saves the last entered image in fieldset.
However, by just giving the form element a proper name, I was able to get around this behaviour:
Upon saving an image I can recall these array paths:
While this works for me, I'm not sure if it is the "Drupal" way or could break anything else. But as I understand, Dmitriy.trt's patch tries to shift this into an automated service (the patch didn't work for me, though).
Regards,
Paul
Edit: Seems I got something messed up with the patches. When it stopped working I tried to investigate further and am now pretty sure what was going on.
When applying the patch, it didn't work for me which was probably the fault of my modules code. Anyhow after removing the patch I wrote my "workaround" above and it worked for me. However, my FTP programme failed on uploading the original file.inc so my code only works if I apply the patch to file.inc. I didn't patch form.inc but used my code instead.
Anyway, the support of file uploads within fieldsets should be provided by core.
Comment #23
WesleyWex CreditAttribution: WesleyWex commentedSo, it has been almost four years since this bug was first reported. This is just disappointing.
Comment #25
madmanmax CreditAttribution: madmanmax commentedStill counting... issue is not fixed. Any updates on the patch?
Comment #26
Wbird CreditAttribution: Wbird commentedsame problem, give up...
Comment #27
qrohlf CreditAttribution: qrohlf commentedI'm attempting to use the fix from #22, but having trouble with it. For now, I am hardcoding the #name and #parents values to be similar to the ones shown above, once I get it working I'll change it to a dynamic name.
My form gets declared like this:
And I try to retrieve the file like this:
When I pick an image to upload and hit submit, the resulting [files] array looks like this:
I've tried lots of variations on this, but file_save_upload always seems to return 0. What am I doing wrong?
If more detail on the issue would be helpful, check my post over here: http://drupal.stackexchange.com/questions/6059/uploading-from-within-fie...
Comment #28
RdeBoerFinding the same in D7....
The $_FILES array does not support nested form elements (i.e. #tree => TRUE on the parent form element).
So each file element on the form must have a unique name, which is a pain when your form can be dynamically extended with more rows/fieldsets via the user pressing "Add another".
Part of the problem (in D7) may be here, in
form.inc
.Note the comment in the code: "we do not support nested file names".
A potentially clue to a fix is somehow manipulating $element['#name'] external to the above function, matching it up with the way the $_FILES array is indexed, very much along the lines of what people have had a go at above.
All in all pretty messy.
Comment #29
RdeBoerSo here is what worked for me in D7.
I have a file selection form element (
#type => 'file'
) inside a fieldset which in itself lives in an outer fieldset on which I've set#tree => TRUE
, thus causing the same problem everyone has been having above.In fact in my case the outer fieldset has 'Add another' and 'Remove last' buttons to allow the user to dynamically add more or remove inner fieldsets. And each of the inner fieldsets, in my case has not 1 but 3 file upload selectors, as '#multiple' appears not to be supported.
Anyway, the code below handles this and similar cases. The great thing about this code is that you do not have to patch core.
You need to:
#name
attribute on thefile
form element to set a unique name of the formfiles[...]
. What you put for the ... is truly arbitrary, as long as it is unique. In my case, because my outer fieldset is called 'products' and my inner fieldsets can grow from 1..many and I have up to 3 files (attachments) I went forfiles[products-$row-attachment$i-fid]
, just to follow the hierarchy of the form. But really I could have just gone for a, b, c, d, e..._validate
function:You'll need to adjust it a little. For example your outer fieldset may not be called 'products'. Also, you may not have the extra 'fid', in which case just drop it.
Now it is clear why you may use any unique identifier for #name: it simply goes through all names in the $_FILES array and then traverses the form to find the matching form element. Then it loads the selected file. Or if there's an error (wrong extension etc.) it highlights in red the offending file upload widget.
Then in your
_submit
handler you pick the fid or fids from $form_state['values'] and save them via variable_set() or whatever mechanism you wish to use.Final note. As the file upload widget does not seem to allow a
#default_value
I display the selected value in the#description
(viafile_load($fid)
) and use a check box next to the file upload widget to remove an existing selection. This then works with the following code, to be inserted in_validate
just before the code above:Comment #31
sreenivasparuchuri CreditAttribution: sreenivasparuchuri commentedI faced the same problem in drupal 8 which i fixed by using
'#name' => "files[upload_image]"
Below is the example
Comment #32
handkerchief@sreenivasparuchuri Thank you so much for this!