Example: Multiple Files Uploader with POST Variables and Server Data Retrieval

In this example, the Uploader is used to send multiple images or videos to the server and monitor their upload progress with individual counters. If the Uploader is used in a browser with HTML5 support, it is progressively enhanced to enable dragging-and-dropping files into the browser window. Along with each file, this example also submits an additional POST variable (the file's name). Once each upload completes, the server sends the received file name POST variable back, along with a time stamp, and the example displays them next to the file.

Please note: This example will not work when run from a local filesystem because of security restrictions in the transport protocols used. If you’d like to run this example locally, set up a local web server and launch it from there.

Also note: You will need compile and host your own flashuploader.swf file to enable Flash mode which is needed for IE <= 9. Necessary source files are available in the yui3-swfs repository.

Also note: The uploader is not supported on iOS devices (iPhone and iPad), because they lack file upload capability. This example provides a graceful degradation message for all such systems.

Also note: The backend script used in these examples does not store any information it receives. Nevertheless, do not submit any sensitive or private data and keep your tests to a few small files to avoid overloading the system.

File nameFile sizePercent uploadedData from Server
No files selected.

Sending and Retrieving Data from the Server

This example is based on the Uploader with HTML5 Drag-and-Drop Support, but adds custom POST variables along with each file upload, and retrieves and displays data received from the server in response to each file upload.

To send additional POST variables along with files, we populate the postVarsPerFile attribute when files are selected:

uploader.after("fileselect", function (event) {

   ...

   var perFileVars = {};

   Y.each(fileList, function (fileInstance) {
       fileTable.append("<tr id='" + fileInstance.get("id") + "_row" + "'>" +
                             "<td class='filename'>" + fileInstance.get("name") + "</td>" +
                             "<td class='filesize'>" + fileInstance.get("size") + "</td>" +
                             "<td class='percentdone'>Hasn't started yet</td>" +
                             "<td class='serverdata'>&nbsp;</td>");

       perFileVars[fileInstance.get("id")] = {filename: fileInstance.get("name")};
   });

   uploader.set("postVarsPerFile", Y.merge(uploader.get("postVarsPerFile"), perFileVars));
});

When uploads complete, we can retrieve and display the data received from the server (in this case, the filename POST variable that we transmitted, along with the server timestamp):

uploader.on("uploadcomplete", function (event) {

    ...

    fileRow.one(".serverdata").setHTML(event.data);
});

Full Source Code For this Example

<style>
#filelist {
    margin-top: 15px;
}

#uploadFilesButtonContainer, #selectFilesButtonContainer, #overallProgress {
    display: inline-block;
}

#overallProgress {
    float: right;
}

.yellowBackground {
  background: #F2E699;
}

.serverdata {
  font-size: 0.8em;
}
</style>

<div id="exampleContainer">
<div id="uploaderContainer">
    <div id="selectFilesButtonContainer">
    </div>
    <div id="uploadFilesButtonContainer">
      <button type="button" id="uploadFilesButton"
              class="yui3-button" style="width:250px; height:35px;">Upload Files</button>
    </div>
    <div id="overallProgress">
    </div>
</div>

<div id="filelist">
  <table id="filenames">
    <thead>
       <tr><th>File name</th><th>File size</th><th>Percent uploaded</th><th>Data from Server</th></tr>
       <tr id="nofiles">
        <td colspan="4" id="ddmessage">
            <strong>No files selected.</strong>
        </td>
       </tr>
    </thead>
    <tbody>
    </tbody>
  </table>
</div>
</div>

<script>

YUI({filter:"raw"}).use("uploader", function(Y) {
Y.one("#overallProgress").set("text", "Uploader type: " + Y.Uploader.TYPE);
   if (Y.Uploader.TYPE != "none" && !Y.UA.ios) {
       var uploader = new Y.Uploader({width: "250px",
                                      height: "35px",
                                      multipleFiles: true,
                                      swfURL: "flashuploader.swf?t=" + Math.random(),
                                      uploadURL: "http://yuilibrary.com/sandbox/upload/",
                                      simLimit: 2,
                                      withCredentials: false
                                     });
       var uploadDone = false;

       if (Y.Uploader.TYPE == "html5") {
          uploader.set("dragAndDropArea", "body");

          Y.one("#ddmessage").setHTML("<strong>Drag and drop files here.</strong>");

          uploader.on(["dragenter", "dragover"], function (event) {
              var ddmessage = Y.one("#ddmessage");
              if (ddmessage) {
                ddmessage.setHTML("<strong>Files detected, drop them here!</strong>");
                ddmessage.addClass("yellowBackground");
              }
           });

           uploader.on(["dragleave", "drop"], function (event) {
              var ddmessage = Y.one("#ddmessage");
              if (ddmessage) {
                ddmessage.setHTML("<strong>Drag and drop files here.</strong>");
                ddmessage.removeClass("yellowBackground");
              }
           });
       }

       uploader.render("#selectFilesButtonContainer");

       uploader.after("fileselect", function (event) {

          var fileList = event.fileList;
          var fileTable = Y.one("#filenames tbody");
          if (fileList.length > 0 && Y.one("#nofiles")) {
            Y.one("#nofiles").remove();
          }

          if (uploadDone) {
            uploadDone = false;
            fileTable.setHTML("");
          }

          var perFileVars = {};

          Y.each(fileList, function (fileInstance) {
              fileTable.append("<tr id='" + fileInstance.get("id") + "_row" + "'>" +
                                    "<td class='filename'>" + fileInstance.get("name") + "</td>" +
                                    "<td class='filesize'>" + fileInstance.get("size") + "</td>" +
                                    "<td class='percentdone'>Hasn't started yet</td>" +
                                    "<td class='serverdata'>&nbsp;</td>");

              perFileVars[fileInstance.get("id")] = {filename: fileInstance.get("name")};
                             });

              uploader.set("postVarsPerFile", Y.merge(uploader.get("postVarsPerFile"), perFileVars));
       });

       uploader.on("uploadprogress", function (event) {
            var fileRow = Y.one("#" + event.file.get("id") + "_row");
                fileRow.one(".percentdone").set("text", event.percentLoaded + "%");
       });

       uploader.on("uploadstart", function (event) {
            uploader.set("enabled", false);
            Y.one("#uploadFilesButton").addClass("yui3-button-disabled");
            Y.one("#uploadFilesButton").detach("click");
       });

       uploader.on("uploadcomplete", function (event) {
            var fileRow = Y.one("#" + event.file.get("id") + "_row");
                fileRow.one(".percentdone").set("text", "Finished!");
                fileRow.one(".serverdata").setHTML(event.data);
       });

       uploader.on("totaluploadprogress", function (event) {
                Y.one("#overallProgress").setHTML("Total uploaded: <strong>" + event.percentLoaded + "%" + "</strong>");
       });

       uploader.on("alluploadscomplete", function (event) {
                     uploader.set("enabled", true);
                     uploader.set("fileList", []);
                     Y.one("#uploadFilesButton").removeClass("yui3-button-disabled");
                     Y.one("#uploadFilesButton").on("click", function () {
                          if (!uploadDone && uploader.get("fileList").length > 0) {
                             uploader.uploadAll();
                          }
                     });
                     Y.one("#overallProgress").set("text", "Uploads complete!");
                     uploadDone = true;
       });

       Y.one("#uploadFilesButton").on("click", function () {
         if (!uploadDone && uploader.get("fileList").length > 0) {
            uploader.uploadAll();
         }
       });
   }
   else {
       Y.one("#uploaderContainer").set("text", "We are sorry, but to use the uploader, you either need a browser that support HTML5 or have the Flash player installed on your computer.");
   }


});

</script>