-1

I am uploading multiple files using Drupal's form API but I am doing it multiple times:

$form['upload-group']['data-sources'] = array(
    '#type'         => 'file', 
    '#name'         => 'datasources[]',
    '#title'        => t('Data Source(s)'), 
    '#attributes'   => array('multiple' => 'multiple'), 
);

$form['upload-group']['ref-attach'] = array(
    '#type'         => 'file', 
    '#name'         => 'attaches[]',
    '#title'        => t('Ref Attachment(s)'), 
    '#attributes'   => array('multiple' => 'multiple'), 
);

I am using the standard code I have used many times before for one multiple upload field on my form. However file_save_upload's first parameter is the index of the array (without any reference to the array name itself.):

$num_files = count($_FILES['datasources']['name']);

for ($i = 0; $i < $num_files; $i++) {

    $file = file_save_upload($i, $validators, 'public://', FILE_EXISTS_REPLACE);

    if ($file) {
        $src = 'public://'.$file->filename;
        $dest = 'public://datasources/'.$file->filename;
        file_unmanaged_move($src, $dest, FILE_EXISTS_REPLACE);
    }
}

My thought is that this is causing confusion as to which array it is trying to upload and why I am not getting anything uploaded at all!!

Has anyone come across this issue before or have any ideas on a solution?

1

file_save_upload() only works on the $_FILES['files'] array. This usually happens automatically because #name in the form element is 'files[]'.

I was on the right lines by using '#name' => 'datasources[]' and '#name' => 'attaches[]'. However, they were not getting uploaded because they weren't named 'files[]'.

I have worked around this by adding a function.

function mymodule_merge_upload_files(&$files, $sourcename) {
  // Number of files added to $_FILES['files'] already (if any)
  $num_sofar = isset($files['files']['name']) ? count($files['files']['name']) : 0;
  // Number of additional files we are appending
  $num_app = count($files[$sourcename]['name']);

  for ($i = 0; $i < $num_app; $i++) {
    $files['files']['name'][$num_sofar] = $files[$sourcename]['name'][$i];
    $files['files']['type'][$num_sofar] = $files[$sourcename]['type'][$i];
    $files['files']['tmp_name'][$num_sofar] = $files[$sourcename~['tmp_name'][$i];
    $files['files']['error'][$num_sofar] = $files[$sourcename]['error'][$i];
    $files['files']['size'][$num_sofar] = $files[$sourcename]['size'][$i];
    $files['files']['source'][$num_sofar] = $sourcename;
    $num_sofar++;
  }    
}

The function merges the uploaded arrays to the $_FILES['files'] array and adds a further sub-array to save where the files came from.

I then modified the submission callback as follows.

mymodule_merge_upload_files($_FILES, 'datasources');
mymodule_merge_upload_files($_FILES, 'attaches');
$num_files = count($_FILES['files']['name']);

for ($i = 0; $i < $num_files; $i++) {
  $file = file_save_upload($i, $validators, 'public://', FILE_EXISTS_REPLACE);
  if ($file) {
    $src = 'public://'.$file->filename;
    $dest = 'public://somefolder/'.$_FILES['files']['source'][$i].'/'.$file->filename;
    file_unmanaged_move($src, $dest, FILE_EXISTS_REPLACE);
  }
}

The first 2 lines merge both arrays using my function, which I can then upload to specific folders based on the source ($_FILES['files']['source'][$i]).

  • @kiamlaluno Thanks for reformatting the text of this answer. I like your formatting better than mine. However, the reformatting of the code itself has made it quite unreadable by comparison to my nicely spaced code and has introduced an error on ['tmp_name'] line where you have changed the ] to a ~ – Angus Walker Jul 16 '17 at 6:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.