Introduction

This plugin will allow the use of a SWFUploadField object as a substitute for a FileField in the CMS or on any custom form on your website. SWFUpload is an open source project that enables the use of Flash-based uploading through Javascript. The use of Flash for uploading brings many rich features to uploading including:

  • Multiple file selection
  • Upload progress
  • File type and size filtering (unwanted file types and sizes are greyed out)

Requirements

Silverstripe 2.2 or later

Installation

Place the swfupload folder in the Silverstripe root and run a /db/build?flush=1 ( /dev/build in 2.3 or later)

Components

SWFUploadField.php

The primary class responsible for generating a SWFUpload field on a form. Subclass of FormField.

SWFUploadConfig.php

A class of static functions used to configure the javascript object for SWFUpload. For more information, see configuration.

SWFUploadFileIFrameField

A subclass of FileIFrameField used to bring SWFUpload features into the CMS.

handlers.js

A series of callback functions that are triggered by a wide variety of events events in the SWFUpload object.

Example Usage

A CMS Field

In this example, we'll add a file upload to the CMS edit form of a page with a File associated with it. Let's exclude all files but PDFs.

 
static $has_one = array ('BigFile' => 'File');
 
public function getCMSFields()
{
	SWFUploadConfig::addFileType('pdf');
        $fields = parent::getCMSFields();
	$fields->addFieldToTab("Root.Content.File", new SWFUploadFileIFrameField('BigFile','Upload a file'));
	return $fields;
}

:swfupload1.gif

That's all there is to it! If you're attaching large files to a page, this is particularly useful because it will display a progress bar for the upload.

A custom form on your website

In this example, we'll use a SWFUploadField to support attaching a cover letter and resume to a job application form. The only file types we'll accept for the cover letter and resume are PDF and DOC.

:swfupload2.gif

Setting up the form

/mysite/code/ResumeForm.php

class ResumeForm_Controller extends PageController
{
  public function ResumeForm()
  {
 
	SWFUploadConfig::addFileTypes(array(
		'pdf','doc'
	));
 
	return new Form(
		$this,
		"ResumeForm",
		new FieldSet(
			new TextField('Name'),
			new TextField('Email'),
			new SWFUploadField(
				"ResumeForm",
				"Resume",
				"Upload your cover letter and resume (pdf or doc format)",
				array (
					'file_upload_limit' => '2',
					'required' => 'true'
				)
			)
		),
		new FieldSet(
			new FormAction('doResumeSubmit','Apply now')
		)	
	);
  }
}

For the most part, this form looks like most other contact forms except for a few extra functions to configure and create the SWFUploadField.

First, we talk to the SWFUploadConfig class to add the allowed file types. Without this function, the SWFUploadField will accept all file types.

The SWFUploadField constructor takes four arguments in this example.

  • “ResumeForm” the name of the form
  • “Resume” the name for the field
  • “Upload your cover letter…“ the label for the field
  • array() an array of configuration variables to pass into the SWFUploadConfig class
  • file_upload_limit: limit the number of files to 2 (a cover letter and a resume)
  • required will hide the submit button on the form until valid files are selected.
Handling the incoming file

The form will now instantiate an asynchronous Flash upload on submit. Now we need to write a script to tell the server how to handle the incoming files. By default, SWFUploadField will execute the handleswfupload() function on the current controller.

/mysite/code/ResumeForm.php

public function handleswfupload()
{
  if(isset($_FILES['swfupload_file']) && is_array($_FILES['swfupload_file']))
    echo Folder::findOrMake('Resumes')->addUploadToFolder($_FILES['swfupload_file']);
  else echo ' ';
}

SWFUpload sends the file in an array named swfupload_file. (This can be changed in SWFUploadConfig). We get a Folder object and add the incoming file to the Folder. We must return the ID of the file to SWFUpload. Fortunately, the addUploadToFolder() returns the most recent generated database ID, so this works perfectly.

In the case of an error, we return a single space to the SWFUpload object.

Handling the form

Now the form will execute its action doResumeSubmit. In handling the form post, we need to be aware of the files that were uploaded so we can do something with them, such as send an email to an admin.

/mysite/code/ResumeForm.php

public function doResumeSubmit($data,$form)
{
 
		if(isset($_POST['uploaded_files']) && is_array($_POST['uploaded_files'])) {
 
			$email = new Email(
				$data['Email'],
				"admin@example.com",
				"New Resume Form"
			);
			$body = "<p>Attahed are the resume and cover letter of " . $data['Name'] . ".</p>";
			$body .=  "<p>Download them from here:</p>";
			foreach($_POST['uploaded_files'] as $id) {
				$file = DataObject::get_by_id("File",$id);
				$body .= "<a href='$file->URL'>$file->Title</a><br />";
 
			}
			$email->body = $body;
			$email->send();
			Director::redirect($this->Link('success'));
		}
}

The $_POST['uploaded_files'] array contains all the IDs of the files that were uploaded through the form. We loop through them and attach them to the email one by one.

Configuration

The SWFUploadField takes many parameters to configure its functionality and appearance. Fortunately, most of these are rarely, if ever, modified.

Changing default values

To change a default value of any SWFUpload configuration parameter, just edit /swfupload/_config.php and change the values of any key/value pair passed to the SWFUploadConfig::Configure() function.

Changing values per instance

Using SWFUploadConfig

The SWFUploadConfig class can be accessed anytime before a SWFUploadField is instantiated to update the configuration. Some common updates have helper functions including:

  • addFileType($type): Takes a file type extension (with or without the dot)
  • addFileTypes(array()): Wrapper function for addFileTypes()
  • addStaticPostParam($param, $value): Extra $_POST parameters to feed to the handleswfupload() function * addStaticPostParams(array()): Wrapper function for addStaticPostParam()
  • addDynamicPostParam($name, $id): Adds a dynamic value to the $_POST to handleswfupload, such as the value entered on a form field. Takes the name you want for the parameter and the ID of the form element from which to get a value. e.g. SWFUploadConfig::addDynamicPostParam('Name','Form_ResumeForm_Name') will return the user input for the Name field in the above form.
  • addDynamicPostParams(array()): Wrapper function for addDynamicPostParam()

For all other configuration updates, use SWFUploadConfig::set_var('var','value').

Using the SWFUploadField Constructor

Any of these key value pairs can be updated on the construction of a SWFUploadField object. For example:

$my_swfupload = new SWFUploadField("ResumeForm","Resume","Upload your resume", array(
'post_params' => array('Foo' => 'Bar'),
'file_upload_limit' => '2'
));

Configuration Glossary

Parameter name Default Value Purpose
form_namenoneProvides a javascript hook for the form containing a SWFUPloadField
upload_urlThe handleswfupload() action on the current controllerThe script that will run when SWFUpload finishes uploading to the server. Handles the file upload.
file_destination_pathnoneDEPRECATED
file_post_nameswfupload_fileName of the array that is passed to the server in $_FILES
post_paramsemptyA javascript object of key/value pairs that will be sent to the upload_url in a $_POST array
file_size_limitThe upload_max_filesize setting in php.iniFiles larger than this number (in kilobytes) are not allowed
file_types_list*.*Files allowed to be uploaded through the SWFUploadField
file_types_descriptionnoneDescribe the types of files allowed, e.g. only images
browse_button_textBrowse…Text that appears on the browse button
file_upload_limit100Maximum number of files that can be uploaded
file_queue_limit100Maximum number of files allowed in the upload queue DEPRECATED
requiredfalseIf set to true (as a string), the submit button will not appear until valid files have been selected
swfupload_loaded_handlerswfUploadLoadedThis Javascript function will fire when the Flash object has been loaded successfully.
file_dialog_start_handlerfileDialogStartThis Javascript function will fire when the dialog box is opened to browse files
file_queued_handlerfileQueuedThis Javascript function will fire when a file has been successfully put into the queue
file_queue_error_handlerfileQueueErrorThie Javascript function will fire when a file has been put into the queue erroneously.
file_dialog_complete_handlerfileDialogCompleteThis Javascript function will fire when a file has been selected from the dialog box
upload_start_handleruploadStartThis Javascript event will fire when the upload begins.
upload_progress_handleruploadProgressThis Javascript event will fire when a progress update is received from the Flash upload API.
upload_error_handleruploadErrorThis Javascript event will fire when an upload results in a server error
upload_success_handleruploadSuccessThis Javascript event will fire when an upload has successfully reached the server
upload_complete_handleruploadCompleteThis Javascript event will fire when the upload has been successfully processed by the server
flash_urlAbsolute path to /swfupload/javascript/swfupload.swfPath to the Flash file that runs SWFUpload
swfupload_element_idflashUIID of the field that will contain the SWFUpload Flash object
degraded_element_iddegradedUIID of the field that will handle the file upload if Flash is not supported
progress_targetfsUploadProgressID of the field that will contain the progress bar during uploading
upload_successfulfalseBoolean for whether the upload is complete
button_image_urlAbsolute path to /swfupload/images/XPButtonNoText_160x22.pngImage of the browse button. Must be an image for Flash 10 compatibility
button_width160Width of the browse button in pixels
button_height22Height of the browse button in pixels
button_text_style.button { font-family: Helvetica, Arial, sans-serif; font-size: 12px; }CSS used to style the button
button_text_top_padding4Padding on the top of the button
button_text_left_padding5Padding on the left of the button
debugfalseIf set to true (as a string), an informative debugging window with tracing will appear near the SWFUploadField.

Troubleshooting

If your SWFUploadField isn't running properly, the first thing you should do is activate debug mode by running

SWFUploadConfig::set_var('debug','true');

before you instantiate your SWFUploadField. You may also add 'debug' ⇒ 'true' to your array of configuration parameters in the SWFUploadField constructor.

The debug mode will provide tracing and verbose error reporting.

"An error occurred in your upload. The server did not accept it." Help!!

This is by far the most common issue with SWFUpload. It is almost always caused by a PHP error on the server, but because Flash will not report PHP errors, only HTTP errors, all we know is that there's a 500 error, which is not very helpful. Fortunately, there's a system in place for debugging this. It's a little tedious, but the good news is, as more errors get debugged, the more stable this module becomes.

First, edit your _config.php and add:

SWFUploadConfig::debug();

This will force the upload script to alert what the server returns in the handleswfupload() method and it will not advance to the form.

  • In your form controller (could be your own, or FileDataObjectManager.php, or ImageGalleryManager.php), edit the function “handleswfupload().” Add a die('hello'); statement to the first line of the function. Now run an upload. You should get an alert message that says “Server said hello”.
  • Now move the die statement further down the code. If you get the same alert message, keep advancing it until you get the upload error message.
  • When you get the upload error, move the die statement back up until you find the exact line that is causing the error, and post it to the DataObjectManager forum “Bug Reports” thread.
  • Undo all of your changes to the controller and _config.php.

For an optimal testing environment, if you're using Firefox, right click on the popup window and select “View frame in new tab.” This will allow you to refresh the screen quickly for each iteration of your testing.

Why don't I see a Browse button?

  • Make sure you are running Flash Player version 10 or higher.
  • Make sure there are no “onload” events conflicting with the SWFUpload Javascript
  • Make sure you do not have an XML doctype.

I'm getting a 404 error in my debug window!

  • Chances are the pathing is wrong for your upload_url. Double check it. Using an absolute URL is helpful for being 100% sure the path is correct.
  • Make sure your upload URL doesn't conflict with any modules you have installed, e.g. gallery/handleswfupload will likely conflict with the gallery module.
 
modules/swfuploadfield.txt · Last modified: 2010/05/05 23:38 (external edit)

Please use comments for notes, tips and corrections about the described functionality.
Use the Silverstripe Forum to ask questions.

blog comments powered by Disqus
 
Except where otherwise noted, content on this wiki is licensed under the following license:CC Attribution-Noncommercial-Share Alike 3.0 Unported
Creative Commons LicenseSilverStripe Documentation by SilverStripe is licensed under a Creative Commons Attribution 3.0 New Zealand License.
Based on a work at doc.silverstripe.com
Recent changes RSS feed Driven by DokuWiki