I'm trying to add upload functionality to a module I'm creating. I just want to upload a single file and write it's path to my database without installing any additional modules. I can get the form item to show up, but I can't get it to process the upload to save my life! I'm just writing it like a page until I can get it figured out, then I'll implement it into my module.

I've been searching for hours and hours and hours for a solution. PLEASE HELP!!

$form = '';
$form .= form_file(t('Upload a file.'), 'upload', 40, t("Upload a file."));
$form .= form_submit(t('Upload')); 
$output = '';
$output .= form($form, $method = 'post', $action = null, $attributes = null);
print theme('page', $output);

$op = $_POST['op'];
$edit = $_POST['edit'];
if ($op == t('Upload')) {
//What in the world goes here?!?!
}

Comments

dmitrig01’s picture

maybe somthing like this, although it doesn't do anything with mysql

if(isset($_FILES[/*input file field name*/]))
	{
		if($_FILES[/*input file field name*/]['error'] == UPLOAD_ERR_OK))
		{
				rename($_FILES[[/*input file field name*/]['tmp_name'], /*directory to upload to*/ . ereg_replace("[[:space:]]","_", /*the name you want*/));
		}
	}
jeepfreak’s picture

Thank you for the response. Unfortunately, it did not work. Nothing was uploaded. I've been trying to use Drupal functions like file_save_upload, but nothing has worked!

BTW - I can handle the mySQL stuff, I just need to get the file uploaded.

Dave Cohen’s picture

Here's what I use to add files to custom node types:

http://cvs.drupal.org/viewcvs/drupal/contributions/sandbox/yogadex/modul...

Unfortuanely for you, that is written for drupal 4.7 and your code appears to be earlier.

Your problem may have to do the forms encoding type. If your code is part of a hook_form(&$node, &$param), try this:

 $param['options'] = array("enctype" => "multipart/form-data");

From your example I can't tell if you're using hook_form. If not, you'll have to figure out an attribute or something to set the encoding type.

jeepfreak’s picture

Well, right now, I'm not working with the form hook, I'm just inserting the code like a page within drupal until I can figure it out. Then I will put it into the form hook.

I changed the following line and now it acts a little more like it's uploading (larger files yield a longer pause, etc), but they still don't save anywhere.

$output .= form($form, $method = 'post', $action = null, $attributes = array("enctype" => "multipart/form-data"));
Dave Cohen’s picture

In 4.6, look to the image.module as an example of how to handle files.

They do not simply save themselves. Drupal provides some methods (file_save_upload, file_check_upload) to help, but its not ideal. By the time you get your custom node handling previewing and submitting, it's a rat's nest (IMHO).

The upload module in 4.7 is OK, but not suitable for custom node types which know exactly what files they need. I think many developers are aware of the shortcomings of the file handling. Someday one of us will submit something better. Could be you... ;)

sepeck’s picture

I believe berkes is playing with some concepts on that front.
http://cvs.drupal.org/viewcvs/drupal/contributions/modules/betterupload/

Various long discussions in the development archives on various appraoches.

-Steven Peck
---------
Test site, always start with a test site.
Drupal Best Practices Guide -|- Black Mountain

-Steven Peck
---------
Test site, always start with a test site.
Drupal Best Practices Guide

jeepfreak’s picture

Thanks for pointing me towards image.module. I spent a lot more time looking at it's code, but it's so much more complex than what I'm trying to do it's hard for me to follow.

jeepfreak’s picture

I just don't get what the problem is. The following code results in:
* file_check_dir = SUCCESS
* file_check_upload = FAILURE

	$form = '';
	$form .= form_file(t('Upload group picture'), 'picture', 40, t("Upload a picture to represent your group."));
    $form .= form_submit(t('Upload')); 
    $output = '';
    $output .= form($form, $method = 'post', $action = null, $attributes = array("enctype" => "multipart/form-data"));
    print theme('page', $output);
    $op = $_POST['op'];
    $edit = $_POST['edit'];
    if ($op == t('Upload')) {
    $uploaddir = 'files';
	if (file_check_directory(&$uploaddir)){
    drupal_set_message("file_check_dir = SUCCESS", 'status');
    }else{
    drupal_set_message("file_check_dir = FAILURE", 'status');
    }	
    $file = $_FILES['picture'];
    if (file_check_upload($file)){
    drupal_set_message("file_check_upload = SUCCESS", 'status');
    }else{
    drupal_set_message("file_check_upload = FAILURE", 'status');
    }
	}

I also tried changing
$file = $_FILES['picture']; to $file = $edit['picture'];

tenrapid’s picture

try

    $file = file_check_upload('picture');
    if ($file){
      drupal_set_message("file_check_upload = SUCCESS", 'status');
    }else{
      drupal_set_message("file_check_upload = FAILURE", 'status');
    }

you can find the filename of the uploaded file in $file->filename or the filesize in $file->filesize

jeepfreak’s picture

* file_check_dir = SUCCESS
* file_check_upload = FAILURE

=(

tenrapid’s picture

Assumed that 'module_upload_page' is your menu callback, then this works for me:

function module_upload_page() {
  $form = '';
  $form .= form_file(t('Upload group picture'), 'picture', 40, t("Upload a picture to represent your group."));
  $form .= form_submit(t('Upload'));
  $output = '';
  $output .= form($form, $method = 'post', $action = null, $attributes = array("enctype" => "multipart/form-data"));
  $op = $_POST['op'];
  $edit = $_POST['edit'];
  if ($op == t('Upload')) {
    $uploaddir = 'files';
    if (file_check_directory(&$uploaddir)){
      drupal_set_message("file_check_dir = SUCCESS", 'status');
    }else{
      drupal_set_message("file_check_dir = FAILURE", 'status');
    }
    $file = file_check_upload('picture');
    if ($file){
      $file = file_save_upload($file);
      drupal_set_message("file_check_upload = SUCCESS", 'status');
      drupal_set_message('$file = '. print_r($file, true), 'status');
    }else{
      drupal_set_message("file_check_upload = FAILURE", 'status');
    }
  }
  print theme('page', $output);
}
jeepfreak’s picture

It works!! Thank you! Thank you! Thank you! Thank you! Thank you!!

nigels’s picture

Hello,

I am trying to do this too, but im not that great at programming, and im getting very confused about where that bit of code goes in the module.

Do you have a complete listing of the working module code, I tried adding it to the page module but I think I may have put the code in the wrong place.

Would be great if you could post it up.

Many thanks

Nigel

coupet’s picture

This would be an excellent addition to Custom Module Development documentation.

Apache is bandwidth limited, PHP is CPU limited, and MySQL is memory limited.

tenrapid’s picture

I've put together a module with an image upload field as an example.

Hope this helps.


/**
 * Implementation of hook_help().
 */
function nodewithupload_help($section) {
  switch ($section) {
    case 'admin/modules#description':
      return t('A simple node with an upload field.');
    case 'node/add#nodewithupload':
      return t('A simple node with an upload field.');
  }
}

/**
 * Implementation of hook_node_name().
 */
function nodewithupload_node_name($node) {
  return t('node with upload');
}

/**
 * Implementation of hook_perm().
 */
function nodewithupload_perm() {
  return array('create nodewithupload', 'edit own nodewithupload');
}

/**
 * Implementation of hook_access().
 */
function nodewithupload_access($op, $node) {
  global $user;

  if ($op == 'create') {
    return user_access('create nodewithupload');
  }

  if ($op == 'update' || $op == 'delete') {
    if (user_access('edit own nodewithupload') && ($user->uid == $node->uid)) {
      return TRUE;
    }
  }
}

/**
 * Implementation of hook_menu().
 */
function nodewithupload_menu($may_cache) {
  $items = array();

  if ($may_cache) {
    $items[] = array('path' => 'node/add/nodewithupload', 'title' => t('node with upload'),
      'access' => user_access('create nodewithupload'));
  }
  return $items;
}

/**
 * Implementation of hook_load().
 */
function nodewithupload_load($node) {
  $additions = db_fetch_object(db_query("SELECT picture FROM {nodewithupload} WHERE nid = %d", $node->nid));
  return $additions;
} 

/**
 * Implementation of hook_form().
 */
function nodewithupload_form(&$node, &$param) {
  $param['options'] = array("enctype" => "multipart/form-data");
  $form = '';
  $form .= form_hidden('picture', $node->picture);
  if ($node->picture) {
    $form .= form_item(t('Group picture'), theme('image', $node->picture));
  }
  $form .= form_file(t('Upload group picture'), 'picture', 40, t("Upload a picture to represent your group."));
  return $form;
}

/**
 * Implementation of hook_validate().
 */
function nodewithupload_validate(&$node) {
  // if the form is not yet submitted 
  if (!isset($_POST['edit'])) {
    // unset session variable set by file_save_upload() for previous temporary uploads
    unset($_SESSION['file_uploads']['picture']);
  }
  
  // check if a file was uploaded
  if ($file = file_check_upload('picture')) {
    // check if it's an image
    if (image_get_info($file->filepath)){
      $node->picture_upload = file_save_upload($file);
      $node->picture = $node->picture_upload->filepath;
    }
  }
}

/**
 * Implementation of hook_insert().
 */
function nodewithupload_insert($node) {
  if ($node->picture_upload) {
    $file = file_save_upload($node->picture_upload, $node->picture_upload->filename);
    $node->picture = $file->filepath;
  }
  db_query("INSERT INTO {nodewithupload} (nid, picture) VALUES (%d, '%s')", $node->nid, $node->picture);
}

/**
 * Implementation of hook_update().
 */
function nodewithupload_update($node) {
  if ($node->picture_upload) {
    $file = file_save_upload($node->picture_upload, $node->picture_upload->filename);
    $node->picture = $file->filepath;
  }
  db_query("DELETE FROM {nodewithupload} WHERE nid = %d", $node->nid);
  db_query("INSERT INTO {nodewithupload} (nid, picture) VALUES (%d, '%s')", $node->nid, $node->picture);
}

/**
 * Implementation of hook_delete().
 */
function nodewithupload_delete($node) {
  db_query("DELETE FROM {nodewithupload} WHERE nid = %d", $node->nid);
}

/**
 * Implementation of hook_view().
 */
function nodewithupload_view(&$node, $teaser = FALSE, $page = FALSE) {
  if ($page) {
    if ($picture = file_create_path($node->picture)) {
      $info = image_get_info($picture);
      $node->body .= '<h3>Group picture:</h3><img src="/'. $picture .'" width="'. $info['width'] .'" height="'.$info['height'] .'" />';
    }
  }
}


nigels’s picture

Thanks very much Tenrapid for that.

Do I need to create a new database for that and if so could you show what fields e,t,c

Thank you very much, this is really helpful!!!

Nigel

tenrapid’s picture

uups, here is the missing piece

CREATE TABLE nodewithupload (
  nid int(10) unsigned NOT NULL default '0',
  picture varchar(255) NOT NULL default '',
  PRIMARY KEY  (nid)
)
jeepfreak’s picture

You are the man! This helps me out sooo much and I'm sure it will help a lot of other people too!! Thank you!

I just have one question...
why not use

db_query("UPDATE (nodewithupload) SET  nodewithupload.picture = '%s' WHERE nodewithupload.nid = '%d'", $node->picture, $node->nid);

instead of 2 queries

db_query("DELETE FROM {nodewithupload} WHERE nid = %d", $node->nid);
db_query("INSERT INTO {nodewithupload} (nid, picture) VALUES (%d, '%s')", $node->nid, $node->picture);

Again, Thank you!!

ymcp’s picture

Any chance that some kind person could provide a v4.7 version of this nodewithupload module? I have tried to convert it myself, but I'm getting very bogged down in the new Forms API. :-(

For what it's worth, here is my attempt at a v4.7 nodewithupload.install file:

<?php
function nodewithupload_install() {
  switch ($GLOBALS['db_type']) {
    case 'mysql':
    case 'mysqli':
      $result = db_query("
        CREATE TABLE IF NOT EXISTS {nodewithupload} (
          nid int(10) unsigned NOT NULL default '0',
          picture varchar(255) NOT NULL default '',
          PRIMARY KEY  (nid)
        ) TYPE=MyISAM /*!40100 DEFAULT CHARACTER SET utf8 */;"
      );

      if ($result) {
        drupal_set_message(t('Created nodewithupload table correctly'));
      }
      else {
        drupal_set_message(t('Error creating nodewithupload table'));
      }
      break;
  }
}
?>

And here is my hook_node_info() that replaces the v4.6 hook_node_name():

function nodewithupload_node_info() {
  return array('nodewithupload' => array('name' => t('nodewithupload'), 'base' => 'nodewithupload'));
}