The YUI Uploader leverages HTML5+XMLHttpRequest 2 or Flash (deprecated) to provide file upload functionality beyond the basic HTTP <input type='file'>
capabilities. Specifically, the Uploader allows for:
Due to Security issues, as of YUI 3.13.0, YUI has made the decision to remove all Flash files from the repository. As a result, you will need compile and host your own flashuploader.swf
file to enable Flash mode. Necessary source files are available in the yui3-swfs repository.
To include the source files for Uploader and its dependencies, first load the YUI seed file if you haven't already loaded it.
<script src="http://yui.yahooapis.com/3.17.2/build/yui/yui-min.js"></script>
Next, create a new YUI instance for your application and populate it with the
modules you need by specifying them as arguments to the YUI().use()
method.
YUI will automatically load any dependencies required by the modules you
specify.
<script> // Create a new YUI instance and populate it with the required modules. YUI().use('uploader', function (Y) { // Uploader is available and ready for use. Add implementation // code here. }); </script>
For more information on creating YUI instances and on the
use()
method, see the
documentation for the YUI Global Object.
uploader-flash
module has been deprecated as of v3.13.0.crossdomain.xml
file that allows access from the location where the uploader SWF file is hosted.
See more in the Backend Setup section below, or read the crossdomain specification on Adobe's website.visibility
set to hidden
, or display
set to none
, whether at initialization of the page, or at any subsequent time. Because of how the Flash Player is instantiated, setting these properties to these values will result in the loss of communication between the Flash player and the DOM. If it's necessary to hide the instance of the Uploader on the page, its width and height should be set to 0.OPTIONS
request to the target server for file uploads (if the target server is different from the one that is hosting the page originating the request). See the Backend Setup section below for more information, or read more about CORS on the HTML5Rocks website.In this section, we'll describe how to use the uploader in detail. First, let's look at the structure of the uploader module under the hood.
The Uploader consists of two classes, one of which is picked dynamically based on the functionality available on the end user's computer. For that reason, Y.Uploader
is an alias that is dynamically assigned either to the Y.UploaderHTML5
(for browsers that implement XMLHttpRequest Level 2) or Y.UploaderFlash
(for browsers that include the Flash player plugin), or otherwise left as an unpopulated namespace when neither functionality is available. Before instantiating the Uploader, the developer can easily determine which of the three options has been loaded by checking the static Y.Uploader.TYPE
property. This property resolves to either "html5"
, "flash"
, or "none"
, and allows the developer to configure the uploader appropriately or otherwise load a different UI.
Due to the limitations of the Flash player, it is only possible to initiate the file selection dialog for Flash-supported file uploads with a direct user input to the Flash player. For that reason, and to maintain the API and configuration consistency, the Uploader is implemented as a "Select Files" button widget in both the HTML5 and the Flash modes. In case of HTML5 uploader, the interaction events are dispatched by the underlying UI control, whereas in case of the Flash uploader, a transparent Flash player overlay is placed on top of the control and captures all mouse events directly. The underlying UI control is customizable by the developer (the selectFilesButton
attribute).
In Flash mode, the Uploader uses the native functionality of the widely adopted Adobe Flash player to provide methods for sending
multiple files to the server and tracking the progress of the uploads. In order to control the Flash player, the Uploader uses the Flash player's built-in ExternalInterface
class for communicating with JavaScript. ExternalInterface
allows JavaScript to call exposed methods on an instance of a Flash player, and allows the instance of the Flash player to call arbitrary global methods in the global JavaScript space.
In order to properly instantiate the Flash player and communicate with it, the Uploader uses YUI SWF utility. The SWF utility
encapsulates the instance of the Flash player and standardizes communication with it (e.g., all Flash player method calls are
wrapped in SWF's callSWF
function; correspondingly, all method calls from the Flash player are exposed as events dispatched by SWF.)
To place the Uploader on the page, simply create a new instance of Y.Uploader
and render it to the container in which it should be placed.
Since Y.Uploader
may not resolve to a fully-featured module if the required functionality is missing, test that the Y.Uploader.TYPE
property
is not set to "none"
first.
It is recommended that you set fixed dimensions in the configurations for the uploader widget, because the underlying button UI control
is by default sized to 100% of the width and height of its parent:
YUI({...}).use('uploader',function (Y) { if (Y.Uploader.TYPE != "none") { var uploader = new Y.Uploader({width: "300px", height: "40px"}).render("#uploaderContainerID"); } });
With the above instantiation, you are allowing the Uploader to automatically choose whether to use UploaderHTML5
or UploaderFlash
as the underlying module. You can always use those modules directly or manually override the alias as follows:
YUI({...}).use('uploader','uploader-flash', function (Y) { Y.Uploader = Y.UploaderFlash; // or Y.Uploader = Y.UploaderHTML5; var uploader = new Y.Uploader(...); });
You can further use the Y.Uploader.TYPE
property to add functionality-specific features to the Uploader based on whether HTML5 or Flash are available. For instance, in the following code snippet, if the Uploader is in HTML5 mode, we assign it a drag-and-drop area where files can be dragged directly into the browser
(functionality which is unavailable in Flash). If it's in Flash mode, we provide a fileFilters
configuration which allows the selection dialog to filter
files by extension (functionality only available in Flash):
YUI({...}).use('uploader', function (Y) { var uploader = new Y.Uploader(...); if (Y.Uploader.TYPE == "html5") { uploader.set("dragAndDropArea", "#divContainer"); uploader.render("#selectFilesButtonContainer"); } else if (Y.Uploader.TYPE == "flash") { uploader.set("fileFilters", [{description:"Images", extensions:"*.jpg;*.png;*.gif"}, {description:"Videos", extensions:"*.avi;*.mov;*.mpg"}]); uploader.render("#selectFilesButtonContainer"); } else { Y.log("No Flash or HTML5 capabilities detected."); } });
The following configuration attributes are specific to the Uploader:
Attribute | Description | Default |
---|---|---|
appendNewFiles |
A Boolean indicating whether newly selected files should be appended to the existing file list, or whether they should replace it. | true |
buttonClassNames |
The names of CSS classes that correspond to different button states of the "Select Files" control. These classes are assigned to the "Select Files" control based on the mouse states reported by the Flash player or by the state of the HTML5 Uploader. The keys for the class names are:
|
{ hover: "yui3-button-hover", active: "yui3-button-active", disabled: "yui3-button-disabled", focus: "yui3-button-selected" } |
dragAndDropArea UploaderHTML5 |
The node that serves as the drop target for files. | null |
enabled |
A Boolean indicating whether the uploader is enabled or disabled for user input. | true |
errorAction |
The action performed when an upload error occurs for a specific file being uploaded. The possible values are:
|
Y.Uploader.Queue.CONTINUE |
fileFieldName |
A String specifying what should be the POST field name for the file content in the upload request. | "Filedata" |
fileFilters UploaderFlash |
An array indicating what fileFilters should be applied to the file selection dialog. Each element in the
array should be an object with the following key-value pairs:
{ description : String, extensions: String of the form"."ext1;.ext2;*.ext3;..." } |
null |
fileList |
The array of files to be uploaded. All elements in the array must be instances of Y.File and be properly instantiated
depending on whether UploaderHTML5 or UploaderFlash is being used. |
[] |
multipleFiles |
A Boolean indicating whether multiple file selection is enabled. | false |
postVarsPerFile |
An object, keyed by fileId, containing sets of key-value pairs that should be passed as POST variables along with each corresponding file. This attribute is only used if no POST variables are specified in the upload method call. | {} |
selectButtonLabel |
The label for the "Select Files" widget. This is the value that replaces the {selectButtonLabel} token in the
Y.Uploader.SELECT_FILES_BUTTON template. |
"Select Files" |
selectFilesButton |
The widget that serves as the "Select Files" control for the file uploader. | HTML Button with YUI3 CSS Button skin |
simLimit |
The number of files that can be uploaded simultaneously if the automatic queue management is used. This value can be in the range between 2 and 5, with the value of 1 or 2 recommended. | 2 |
swfURL UploaderFlash |
The URL to the SWF file of the flash uploader. A copy local to the server that hosts the page on
which the uploader appears is recommended. NOTE: You will need compile and host your own flashuploader.swf file to enable this Flash mode. Necessary source files are available in the yui3-swfs repository. |
flashuploader.swf |
tabElements UploaderFlash |
The id 's or Node references of the DOM elements that precede and follow the "Select Files" button in the tab order.
Specifying these allows keyboard navigation to and from the Flash player layer of the uploader. The two keys
corresponding to the DOM elements are:
|
null |
uploadURL |
The URL to which file upload requested are POSTed. Only used if a different url is not passed to the upload method call. | "" |
While the file selection dialog in the Uploader is standard for the user's specific operating system, you can specify whether you want the user to be able to select multiple files, or just one:
uploader.set("multipleFiles", true);
After the user has selected a file (or files) to be uploaded, the selected file list is places into the fileList
attribute of the Uploader. At that point,
you can either have the user initialize the actual upload process, or initialize it automatically, without any additional user action.
Each of the selected files is uploaded in its own POST request. You can either upload each file individually, and manage the queue on your own, or use the Uploader's built-in queue management. To upload a single file "manually" (without using automatic queue management), the following method call can be made:
var firstFile = uploader.get("fileList")[0]; uploader.upload(firstFile, "http://url.to/upload.php", {postvar1: "foo", postvar2: "bar"});
To upload all files using the built-in queue manager, you can call the uploadAll()
method:
uploader.uploadAll("http://url.to/upload.php");
You can also upload a subset of the provided files, using the uploadThese()
method:
var firstFive = uploader.get("fileList").slice(0,5); uploader.uploadThese(firstFive, "upload.php");
When using the automatic queue management, you can monitor the overall upload progress by subscribing to the totaluploadprogress
event, which reports the number of bytes uploaded, the total number of bytes, and the percentage of the upload completed:
uploader.on("totaluploadprogress", reportProgress); function reportProgress (event) { Y.log("Bytes uploaded: " + event.bytesLoaded); Y.log("Bytes remaining: " + (event.bytesTotal - event.bytesLoaded)); Y.log("Percent uploaded: " + event.percentLoaded); }
Individual file upload progress is also reported, via the uploadprogress
, uploadcomplete
, and uploaderror
events described below.
During the automatic queue management of multiple files, you can call various methods on the Uploader queue (available as uploaderInstance.queue
)
in order to control the file upload. The methods available to you include:
For more information, see the API Docs for Uploader.Queue.
Uploader fires the following events during operation:
Event | Cause | Payload |
---|---|---|
alluploadscomplete |
Signals that the upload process of the entire file list has been completed. | None |
click UploaderFlash |
Signals that a mouse has been clicked over the Select Files button. |
None |
dragenter UploaderHTML5 |
Signals that a dragged object has entered into the uploader's associated drag-and-drop area (if one is specified). | None |
dragleave UploaderHTML5 |
Signals that a dragged object has entered into the uploader's associated drag-and-drop area (if one is specified). | None |
dragleave UploaderHTML5 |
Signals that an object has been dragged off of the uploader's associated drag-and-drop area (if one is specified). | None |
dragover UploaderHTML5 |
Signals that an object has been dragged over the uploader's associated drag-and-drop area (if one is specified). | None |
drop UploaderHTML5 |
Signals that an object has been dropped over the uploader's associated drag-and-drop area (if one is specified). | None |
fileselect |
Signals that files have been selected. | fileList : An Array of files selected by the user, encapsulated in Y.File |
fileuploadstart |
Signals that the upload of multiple files has been started. |
|
mousedown UploaderFlash |
Signals that a mouse has been pressed over the Select Files button. |
None |
mouseenter UploaderFlash |
Signals that a mouse has begun hovering over the Select Files button. |
None |
mouseleave UploaderFlash |
Signals that a mouse has stopped hovering over the Select Files button. |
None |
mouseup UploaderFlash |
Signals that a mouse has been released over the Select Files button. |
None |
totaluploadprogress |
Reports on the total upload progress of the file list. |
|
uploadcomplete |
Signals that a single file upload has been completed. |
|
uploaderror |
Signals that a error has occurred in a specific file's upload process. |
|
uploadprogress |
Reports on upload progress of a specific file. |
|
uploadstart |
Signals that an upload of multiple files has been started. | None |
See the API documentation for UploaderHTML5 and UploaderFlash for a complete documentation of the Uploader events, methods, attributes, and properties.
Unless the server receiving the file uploads is located on the same domain as the SWF file that is dispatching the uploads, the receiving server must include a crossdomain.xml file allowing the server on which the SWF is located to make requests to it. Consider, for instance, the crossdomain.xml policy file on yahoo.com. It looks as follows:
<cross-domain-policy> <allow-access-from domain="*.yahoo.com" secure="false"/> </cross-domain-policy>
The allow-access-from
parameter specifies which domains hosting SWFs can access yahoo.com: in this case, only subdomains of yahoo.com are allowed to do so. Note, for instance, that CNN.com's list is considerably larger.
If you are planning on using the CDN-hosted Uploader SWF, your crossdomain.xml file might look something like this:
<cross-domain-policy> <allow-access-from domain="yui.yahooapis.com" secure="false"/> </cross-domain-policy>
The security policy for XMLHttpRequest Level 2 cross-domain requests is a little bit trickier. Instead of using separate files, XHR2 uses server-supplied headers to determine whether a request can be made. Before the regular POST request, XHR submits a preflight OPTIONS request with an Origin
parameter. In response, it expects a Access-Control-Allow-Origin
header with a wildcard or a URL matching the Origin
parameter it sent. This header can be set either through the web server you are using, or directly by the script output. For instance, here is a PHP example that replies to the OPTIONS requests with a header allowing all origins:
if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') { header('Access-Control-Allow-Origin: *'); exit; }
Note that the actual response must also contain the Access-Control-Allow-Origin
header.
To learn more about XHR2 cross-domain requests, read this helpful tutorial on html5rocks.com.