File upload flash to drupal

Events happening in the community are now at Drupal community events on www.drupal.org.
You are viewing a wiki page. You are welcome to join the group and then edit it. Be bold!

This is a proof of concept for file upload using flash 8 and drupal 6 + amfphp

Limitations
The filename has to be unique so it can be matched when saving the node
File upload in flash uses FileData, flash 9 should be able to change this to Files so we (probably) can use the build in file upload?

Flash code

var fileListener:Object = new Object();

fileListener.onSelect = function(file:FileReference):Void {
  // second ("files") and third (false) parameter only work in flash 9
  // file.upload has no return value so you have to pass a unique name (see drupal code)
  file.upload("http://example.com/servicefileupload/" + apiKey + "/" + sessId + "/uniquefilename", "files", false);
}

fileListener.onComplete = function(file:FileReference):Void {
  createNode();
}

uploadtest.onRelease = function () {
  var fileRef:FileReference = new FileReference();
  fileRef.addListener(fileListener);
  fileRef.browse([{description: "CV", extension: ".doc;.docx;.pdf;.rtf"}]);
}

function createNode():Void {
  var nsoll = new Object;
  nsoll.nid = 0;
  nsoll.uid = drupal_UserId;
  nsoll.name = drupal_UserName;
  nsoll.changed = true;
  nsoll.type = 'nodetype';
  nsoll.title = 'title';
  nsoll.body = 'body';

  nsoll.field_naam = new Array();
  nsoll.field_naam[0] = new Array();
  nsoll.field_naam[0]['value'] = 'mijn naam';

  nsoll.files = new Array();
  nsoll.files[0] = new Array();
  nsoll.files[0]['fid'] = 0;
  nsoll.files[0]['list'] = 1;
  nsoll.files[0]['description'] = 'uniquefilename'; // same as above
  nsoll.files[0]['weight'] = 0;
 
  var pc:PendingCall = node.save(apiKey, sessId, nsoll);
  pc.responder = new RelayResponder(this, "nodeSave_Result", "nodeSave_Fault");

}

service.module additions

// in function services_menu() {

  // fileupload
  $items['servicefileupload/%'] = array(
    'access arguments' => array('access services'),
    'page callback' => 'services_servicefileupload',
    'page arguments' => array(2),
    'type' => MENU_CALLBACK,
  );

// new stuff

function services_servicefileupload($arg0, $arg1, $arg2) {

// $arg2 is the new name of the file
// apiKey and sessId aren't checked for the moment!

  global $user;

  if (is_uploaded_file($_FILES['Filedata']['tmp_name'])) {

    // Begin building file object.
    $file = new stdClass();
    $file->filename = file_munge_filename(trim(basename($_FILES['Filedata']['name']), '.'), $extensions);
    $file->filepath = $_FILES['Filedata']['tmp_name'];
    $file->filemime = $_FILES['Filedata']['type'];

    // Rename potentially executable files, to help prevent exploits.
    if (preg_match('/.(php|pl|py|cgi|asp|js)$/i', $file->filename) && (substr($file->filename, -4) != '.txt')) {
      $file->filemime = 'text/plain';
      $file->filepath .= '.txt';
      $file->filename .= '.txt';
    }

    // If the destination is not provided, or is not writable, then use the
    // temporary directory.
    if (empty($dest) || file_check_path($dest) === FALSE) {
      $dest = file_directory_temp();
    }

    $file->source = $source;
    $file->destination = file_destination(file_create_path($dest .'/'. $arg2), $replace);
    $file->filename = $arg2;
    $file->filesize = $_FILES['Filedata']['size'];

    // Move uploaded files from PHP's upload_tmp_dir to Drupal's temporary directory.
    // This overcomes open_basedir restrictions for future file operations.
    $file->filepath = $file->destination;
    if (!move_uploaded_file($_FILES['Filedata']['tmp_name'], $file->filepath)) {
      form_set_error($source, t('File upload error. Could not move uploaded file.'));
      watchdog('file', 'Upload error. Could not move uploaded file %file to destination %destination.', array('%file' => $file->filename, '%destination' => $file->filepath));
      return 0;
    }

    // If we made it this far it's safe to record this file in the database.
    $file->uid = $user->uid;
    $file->status = FILE_STATUS_TEMPORARY;
    $file->timestamp = time();
    drupal_write_record('files', $file);

  }

}

node_service.module additions

// $file->description is used to match the file uploaded by flash since we need the fid
// only tested this for creating nodes, no idea what happens if you try to save an existing node :/

function node_service_save($edit) {
 
  // validate node 
  node_validate($edit);

  if ($errors = form_get_errors()) {
    return services_error(implode("\n", $errors));
  }

  $node = node_submit($edit);
  node_save($node);

  if (is_array($node->files)) {

    foreach ($node->files as $fid => $file) {
      // Convert file to object for compatibility
      $file = (object)$file;

      $result = db_query('SELECT DISTINCT f.fid FROM {files} f WHERE f.status = 0 AND f.filename = \'%s\'', $file->description);
        while ($f = db_fetch_object($result)) {
          $file->fid = $f->fid;
      }

      db_query("INSERT INTO {upload} (fid, nid, vid, list, description, weight) VALUES (%d, %d, %d, %d, '%s', %d)", $file->fid, $node->nid, $node->vid, $file->list, $file->description, $file->weight);
      file_set_status($file, FILE_STATUS_PERMANENT);
    }
   
  }
 
  watchdog('content', 'node created', WATCHDOG_NOTICE, l('view', 'node/'. $node->nid));
  return $node;
}

Services

Group organizers

Group categories

Group notifications

This group offers an RSS feed. Or subscribe to these personalized, sitewide feeds: