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;
}