hi all,

i am developing a module that requires a file from the user. But upload does not work.

i have been stuck for the longest time on the form file type "file".

here are my problems:
1- i have know idea how to access $uploads_path that i created in _admin, from _admin_validate. or anywhere else for that matter. In my code i have hard-coded it.

2- the file_save_upload does not want to upload any file to the $uploads_path. i tried everything i can find out on this. it returns 0. that's all. the field name, the uploads path are all correct, but still the uploads_path dir is empty.

here is my code:

function _MY_MODULE_admin(){
    // Make sure Directory for uploads exists. create if not.
    $uploads_path = file_create_path('sites/default/files/_MY_MODULE/uploads');
    if (!file_check_directory($path)) {
      $uploads_path = file_directory_path() . '/_MY_MODULE';
      file_check_directory($uploads_path, FILE_CREATE_DIRECTORY);
      $uploads_path .= '/uploads';
      file_check_directory($uploads_path, FILE_CREATE_DIRECTORY);
    }
    $path = variable_get('uploads_path', $uploads_path);

  // Form components: Fieldset with and input type 'file' for now.
  $form = array();
  $form['#attributes']['enctype'] = "multipart/form-data";

  $form['settings'] = array(
    '#type' => 'fieldset',
    '#collapsible' => TRUE,
    '#title' => t('_MY_MODULE settings'),
      );

  $form['settings']['_MY_MODULE_filename'] = array(
    '#type' => 'file',
    '#title' => t('Enter Path to import File'),
    '#description' => t('Click "Browse" to select a file to upload.'),
    );

  return system_settings_form($form);
}   //end of function _MY_MODULE_admin

function _MY_MODULE_admin_validate($form, &$form_state){
   $validations = array();

   $uploads_path = "sites/default/_MY_MODULE/uploads/";
   
   $saved_file = file_save_upload('_MY_MODULE_filename', $validations, $uploads_path);
   if(!$saved_file){
      drupal_set_message(t('The uploaded file was unable to be saved.'), 'error');
      form_set_error($file_name, 'Error uploading file.');
   }
   else {
      drupal_set_message(t('The uploaded file %filename was saved.'), 'error');
      $form_state['values']['_MY_MODULE_filename'] = $saved_file;
   }
}   // end of function  _MY_MODULE_validate



Comments

vasi1186’s picture

Maybe your php is not configured well... In php.ini, make sure that you have these values set:

file_uploads = On

upload_tmp_dir = a_temporary_directory (On this directory you should have a write access for all users). In Linux, it is usually "/tmp"

upload_max_filesize = 10M (This is the maximum file size allowed for update). Be aware that there is also another variable: "post_max_size". This is the maximum size for post allowed. If your post_max_size is set to 10M, then your upload_max_filesize will be maximum 5 M, no matter if you set it to a great value then 5.

Also, make sure that your folder: "sites/default/files/_MY_MODULE/uploads" has the write permission for the apache user (or for all users).

I hope this will help you.

Vasi.

fawzi’s picture

Hi Vasi,

thanks for your quick reply. still i am not able to upload any files.

i checked my php.ini. it is correct. i am on a MAC, so here are my settings now:

file_uploads = On
upload_tmp_dir =/var/tmp
upload_max_filesize = 10M

Also my "sites/default/files/_MY_MODULE/uploads has read/write permission. (chmod 777 )

I printed the $_FILES to see what is going on. here is the output:

files =>
 name => zimple_filename => arrow.png
 type => zimple_filename => image/png
 tmp_name => zimple_filename => /private/var/tmp/phpIrVkCJ
 error =>zimple_filename => 0
 size => zimple_filename => 3604

All file info is correct, but when i go to /private/var/tmp/, i cannot find the file name that is shown in the $_FILES[tmp_name].
Any ideas???
also if i am going to use sites/default/files/_MY_MODULE/ shouldn't i leave the php.ini tmp dir commented out?

fawzi’s picture

this code works...

   //$saved_file = file_save_upload('_MY_MODULE_filename');             // does NOT send file to /var/tmp
   //$saved_file = file_save_upload('_MY_MODULE_filename', $validations);  // does NOT work
   $saved_file = file_save_upload('_MY_MODULE_filename', $validations, $uploads_path);// works. 
   //$saved_file = file_save_upload('_MY_MODULE_filename', $validations, $dest_file);// does not work. dest_file=uploads_path+filename
   if($saved_file){
     $form_state['values']['_MY_MODULE_filename'] = $saved_file;
   }

i do not know why, since i tried this combination before.
The only thing that is different, that i confirmed is that you cannot leave "upload_tmp_dir " commented out in the php.ini.
Is that a known fact, or is it a fluke?
finally, how do i pass the file to other hooks?
My $form_state[values][_MY_MODULE_filename] is not seen in my _MY_MODULE_page();

vasi1186’s picture

I see two solutions to make available the file in other modules:

1) In each module, implement the hook_form_alter and for this form add a submit callback. In the submit callback you will have access to the $_FILES array directly.

2)
- make a custom hook. lets say the the hook is called hook_MY_MODULE_NAME. After you save and prepare your file, just make this call: module_invoke_all("MY_MODULE_NAME.", 'uploaded _file', $saved_file). This will invoke all functions that are named this way: custom_module_name_MY_MODULE_NAME().

- In your other modules, implement the function "custom_module_name_MY_MODULE_NAME($op, $saved_file)". Make a "switch" or "if" and check for $op=='uploaded_file'. Add your code there, and that's all... I think this solution is more elegant than the first one.

Vasi.

fawzi’s picture

Hi vasi,
thanks for your reply again...i am still learning this stuff, so a lot of what you said will take some study before it sinks in.

-I am sure i will get to a point where i need to pass information across modules. but for now i cannot even pass anything to _MY_MODULE_my_page() in the SAME module. somehow every Global variable is blank.

- my hook_admin() and hook_admin_validate() work fine now, and i do see my uploaded file in the /sites/default/files/my_module/uploads.
But when i go to my _MY_MODULE_my_page() where i would like to process that uploaded file, i cannot open it since $_FILES, $_POST are empty and thus i cannot access the file path and filename.
- I even created a global array to put these values in so i can see them across functions within my module and that does not work either. I am clueless to what i am missing. i am searching up and down drupal's website but i am not having much luck.

so why is it that i cannot see any globals that i have created in my module??????

here is how i defined the global and put in the beginning of _MY_MODULE.module file.:

$_MY_MODULE;
$_MY_MODULE = array();

of course i did put this line of code in every function : global $_MY_MODULE;

here is how i defined that page that will process the uploaded file

 $items['_MY_MODULE'] = array(
    'title' => '_MY_MODULE',
    'page callback' => '_MY_MODULE_my_page',
    'page arguments' => array('MY_MODULE_my_page'),   // Add more arguments in this array if needed.
    'access arguments' => array('access _MY_MODULE content'),
    'type' => MENU_NORMAL_ITEM
    //'type' => MENU_CALLBACK,
  );

i am not sure if this ties to point 1 from your last response, since i am trying to access $_FILES.

Any ideas or pointers would save me my sanity at this point.. :)

thanks,

vasi1186’s picture

When you define the global variable, you also have to put "global" in front of the variable. So, in the begin of the module, you should have this:

global $_MY_MODULE;
$_MY_MODULE = array();

Of course, as you said, everywhere in the module where you want to use this variable, you must use "global" keyword.

fawzi’s picture

But i did that. i did have global in the begining and in every function that would need to use it.
so i still have to figure out what i am doing wrong...

what about $_FILES? is there a reason why i can only access it in _admin() and _admin_validate() and not in _my_page()?

vasi1186’s picture

If your "_my_page" function is called after a redirect, the $_FILES array is empty, so you do not have access to it... Can you paste here the module code?

fawzi’s picture

Hi vasi,

here is the code, hope it is not to long.

- the module name is Zimple
- the idea is to get a filename using the settings menu
- that file name will contain information about the form to display when requested later from the main menu.

- $_ZIMPLE is the array that i thought that i would use to hold the variables that i need in my module. is there a better way to deal with this?

I think i may have found one error... that is in copying the $_FILE into $_ZIMPLE. I am not sure if the "=" means by reference, in which case i cannot find the $_FILES values in $_ZIMPLE.

<?php
// $Id$: zimple.module, v0.001 2009/10/23 00:25:00

//  Include Files
//include_once 'myFunc.php';

global $_ZIMPLE;
$_ZIMPLE = array();

//---------------------------------------------------------------------//
//---------------------------------------------------------------------//
function zimple_help($path, $arg) {
  global $_ZIMPLE;

  $output = '';  //declare your output variable
  switch ($path) {
    case "admin/help#zimple":
      $output = '<p>'.  "Create a form specified by an zimple file." .'</p>';
      break;
  }
  return $output;
} // function zimple_help

//---------------------------------------------------------------------//
//---------------------------------------------------------------------//
function zimple_menu() {
  global $_ZIMPLE;

  $items = array();

  $items['admin/settings/zimple'] = array(
    'title' => 'Zimple settings',
    'description' => 'Description of zimple Module',
    'page callback' => 'drupal_get_form',
    'page arguments' => array('zimple_admin'),    // Add more arguments in this array if needed.
    'access arguments' => array('access administration pages'),
    'type' => MENU_NORMAL_ITEM,
   );

  //Let our menu know of our function that generates a page zimple_my_page()
  $items['zimple'] = array(
    'title' => 'Zimple',
    'page callback' => 'zimple_my_page',
    'page arguments' => array('zimple_my_page'),   // Add more arguments in this array if needed.
    'access arguments' => array('access zimple content'),
    'type' => MENU_NORMAL_ITEM
    //'type' => MENU_CALLBACK,
  );

  return $items;
} 

//---------------------------------------------------------------------//
//---------------------------------------------------------------------//
function zimple_admin(){
  global $_ZIMPLE;

    // Make sure Directory for uploads exists. create if not.
    $uploads_path = file_create_path('sites/default/files/zimple/uploads');
    if (!file_check_directory($path)) {
      $uploads_path = file_directory_path() . '/zimple';
      file_check_directory($uploads_path, FILE_CREATE_DIRECTORY);
      $uploads_path .= '/uploads';
      file_check_directory($uploads_path, FILE_CREATE_DIRECTORY);
    }
    $_ZIMPLE[uploads_path] = $uploads_path;

  // Form components:  an input type 'file' for now.
  $zimple_form = array();
  $zimple_form['#attributes']['enctype'] = "multipart/form-data";

  $zimple_form['zimple_filename'] = array(
    '#type' => 'file',
    '#title' => t('Enter Path to import File'),
    '#description' => t('Click "Browse" to select a file to upload.'),
    );

  return system_settings_form($zimple_form); 
}   //end of function zimple_admin

//---------------------------------------------------------------------//
//                        hook zimple_admin_validate
//     Validate the Settings Form 
//---------------------------------------------------------------------//
function zimple_admin_validate($form, &$form_state){ 
  global $_ZIMPLE;

  $validators = array(
    'file_validate_extensions' => array('zimple'),
    'file_validate_size' => array(10* 1024 * 1024),
    //'file_validate_is_image' => array(),
    //'file_validate_image_resolution' => array(variable_get('user_picture_dimensions', '85x85')),
  );

   $uploads_path = $_ZIMPLE[uploads_path];
   drupal_set_message("uploads_path = $uploads_path", 'status');

   $_ZIMPLE[_FILES] = $_FILES;
   $zimple_filename = $_ZIMPLE[_FILES][files][name][zimple_filename];
   drupal_set_message("zimple_filename = $zimple_filename", 'status');

   $dest_file = $uploads_path . $zimple_filename;
   drupal_set_message("dest_file = $dest_file", 'status');

if (isset($_FILES['files']) && is_uploaded_file($_FILES['files']['tmp_name'][zimple_filename])) {
   $saved_file = file_save_upload('zimple_filename', $validators, $uploads_path);// works.

   if(!$saved_file){
      drupal_set_message('The uploaded file was unable to be saved.', 'warning');
      form_set_error($zimple_filename, 'Error uploading file.');
   }
   else {
      drupal_set_message('The uploaded file %zimple_filename was saved.', 'status');
      $form_state['values']['zimple_filename'] = $saved_file;
       $_ZIMPLE[_FILES][files][name][zimple_filename] = $zimple_filename;
   }
   }
  drupal_set_message('<pre>'. 'zimple_validate:_ZIMPLE: ' . var_export($_ZIMPLE, TRUE) .'</pre>');
}   // end of function  zimple_validate

//---------------------------------------------------------------------//
//               hook My_page
//  This is where we create our page.
//  Same as zimple_block, but generates a Page content instead of a block
//---------------------------------------------------------------------//
function zimple_my_page() {
  global $_ZIMPLE;

  drupal_set_message('<pre>'. 'zimple_validate:_ZIMPLE: ' . var_export($_ZIMPLE, TRUE) .'</pre>');

  $uploads_path    = $_ZIMPLE[uploads_path];
  $zimple_filename = $_ZIMPLE[_FILES][files][name][zimple_filename];

  //$dest_file = $uploads_path . $zimple_filename;
  //drupal_set_message("dest_file = $dest_file", 'status');

  //$zimple_ar = drupal_get_form('zimple_form');

  return TRUE;//$zimple_ar;
}   // end of function zimple_my_page


//---------------------------------------------------------------------//
//   generate the code for the form by running zimple_parse on the zimple fie.
//---------------------------------------------------------------------//
function zimple_form(){
  global $_ZIMPLE;

   $uploads_path = $_ZIMPLE[uploads_path];
   $zimple_filename = $_ZIMPLE[_FILES][files][name][zimple_filename];

   $dest_file = $uploads_path . $zimple_filename;

   drupal_set_message("dest_file = $dest_file", 'status');

  $zimple_ar = zimple_parse($dest_file);

  return $zimple_ar;
}   //   end of function zimple_form

fawzi’s picture

Hi Vasi,

thanks for the earlier help.

Just for the record i had to 2 things to make it work:
1-
- i thought ofusing SESSION super global
- this is what i added in the top of my zimple.module code:

if(!isset($_SESSION['_ZIMPLE']))
  {
    $_SESSION['_ZIMPLE'] = array();
  }

- From then on, i was able to store and retrieve my variables from any functionin my module as usual: $_SESSION[zimple][myNewVar] = 'newVar'.

2-
- I modified my [drupal_root]/sites/default/settings.php.
- I set $base_url = 'http://localhost/myDrupal';.
- this is per recommendation of one of the sites(http://drupal.org/node/575002). Since the sessions id might not be the same in case of redirection...well that's what i understood from it.

regards

vasi1186’s picture

ok, you're welcome!

pria’s picture

How about the submit_form($form, &$form_state) ?
I want to upload the file into my database but upload doesn't work.. Can you help me?