Uploading Folders with HTML5 Uploader (JavaScript API)

Uploading folders is extremely useful when users are allowed to upload large amounts of files. This topic describes how to enable this feature in HTML5 Uploader and restore the folder structure on the server.

Uploading Folders on Client Side

To turn the folder uploading on in the HTML5 Uploader, just set the imageUploaderFlash.folderProcessingMode property to one of the following values:

  • None (same as Skip) - turns off the folder uploading.
  • Mixed (same as Show and Upload) - enables both files and folder uploading.
  • Folder - allows only folders.

Note, that you can use the values accepted by Java/ActiveX uploader as well for compatibility.

Important

HTML5 Uploader supports folder uploads only in Chrome. If you want to use it with other browsers as well, it is recommended to use both Java/ActiveX and HTML5/Flash uploaders together as discussed below.

When you turn this feature on, it affects not only the open file/folder dialog, but also drag-and-drop functionality. All its subfolders become selected recursively.

Note

There is a limitation in Google Chrome for a number of files added when you drop a folder - it adds not more than 100 files per a folder. This limitation is not applied if the user adds a folder using a dialog. There is no official information from Google regarding this issue, so it is probably happens only on particular versions.

Here is an example how to use the folderProcessingMode property:

JavaScript
var u = $au.imageUploaderFlash({
    id: 'Uploader1',
    // other params
    folderProcessingMode: 'Mixed'
});

In this case, if a user selects a folder, all the files in this folder will be recursively added to the upload pane (except of ones filtered due to the restrictions); so a user can clearly see all the files selected at once. When a user starts the upload, the HTML5 Uploader sends the folder structure information (i.e. relative paths) along with file names. For instance, if a user sends a MyDocuments folder, which contains a MyPhotos subfolder, all files inside this subfolder will be sent to a server along with MyDocuments\MyPhotos\filename relative paths and all files contained directly in the MyDocuments folder will have MyDocuments\filename relative paths.

If you need to access the folder structure of a selected file before the upload, from your JavaScript code, you can use (both getter and setter).

Note

It is impossible to get the uploader to send absolute paths.

Restoring Folders Structure on Server Side

As stated in the previous section, when the folder is uploaded, the SourceName_i POST field will contain not only the filename but also a relative path to the ith file. So, if you want to restore folders structure on the server, you should parse the SourceName_i field and recreate a path to the ith file, folder by folder. The following algorithm describes this idea more detailed:

  1. Define the folder to save uploaded folders to.
  2. Iterate through all files uploaded in the current package (their total number is contained in the PackageFileCount field).

    In this loop:

    1. Read a relative path to each received file from the SourceName_i POST field, where i is an index of this file.
    2. Parse this path to get all the folder names and the file name.
    3. Append the relative path to the path defined on the first step.
    4. Save the file to this path.

Here is a pseudocode for this algorithm:

pseudocode
//The folder to save uploaded folders to
string catalogPath
    
iterate through each file (i)
{
    // Check if it is POST request
    if not (RequestMethod is POST) 
        exit();
    
    //Take the value from the SourceName_i POST field
    string relativePath = POST["SourceName_" + i]
    
    //The 'split' function splits a string into an array of substrings using
    //the specified delimiter ('\' in our case)
    array folderStructure = split(relativePath, "\")
    
    //The 'count' function returns number of elements in array
    integer folderCount = count(folderStructure) 
    
    //This value containes only the name of received file
    string fileName = folderStructure[folderCount]
    
    //The 'goToFolder' function changes the current working folder to the specified one
    goToFolder(catalogPath)
    
    //iterate through all but last one folder names 
    iterate through folderCount-1 elements of folderStructure (j)
    {
        //The 'exists' function checks if the specified folder exists under the current location
        if not exists(folderStructure[j])
        {
            //The 'createFolder' function creates a subfolder
            createFolder(folderStructure[j])
        }
        goToFolder(folderStructure[j])
    }
    
    //The 'save' function saves the i-th file in the current working folder with the fileName name
    save(file[i], fileName)
}

Using both HTML5 and Java uploaders together

You may find it annoying that the folder uploading functionality is supported only by Google. To be able to upload folders from other browsers than Chrome, you have to use Java/ActivX uploader there. Here is the example how to do it:

JavaScript
<!DOCTYPE html>                        
<html>
<head>
	<title>Uploading folders in any browser</title>
	<link rel="stylesheet" type="text/css" href="../../aurigma/last/fh/css/aurigma.htmluploader.control.css" />
	<script src="../../aurigma/last/fh/aurigma.imageuploaderflash.js"></script>
	<script src="../../aurigma/last/fh/aurigma.htmluploader.control.js"></script>
	<script src="../../aurigma/last/aj/aurigma.uploader.js"></script>
</head>
<body>
    <script type="text/javascript">
         
        // Browser detection method is found at
        // http://stackoverflow.com/questions/9847580/how-to-detect-safari-chrome-ie-firefox-and-opera-browser
        var isChrome = !!window.chrome && navigator.userAgent.indexOf(' OPR/') < 0;
                 
        var uploader;
        if (isChrome) {
            uploader = Aurigma.ImageUploaderFlash.imageUploaderFlash({
                    id: "aurigma-fh1"
                    // insert HTML5/Flash-specific params here
            });
        } else {
            uploader = Aurigma.ImageUploader.uploader({
                    id: "aurigma-aj1",
                    activeXControl: {
			codeBase: "../../aurigma/last/aj/Uploader8.cab", 
			codeBase64: "../../aurigma/last/aj/Uploader8_x64.cab"},
                    javaControl: {codeBase: "../../aurigma/last/aj/Uploader8.jar"},
                    folderPane: {
			viewMode: 'Details'
		    },
		    uploadSettings: { filesPerPackage: 1 },
		    detailsViewColumns: { dimensionsText: '', infoText: '' }
 
		    // insert Java/ActivX-specific params here
                    });
        }
        uploader.set({
	    folderProcessingMode: 'Mixed',
	    uploadPane: { viewMode: 'Tiles' },
            converters: [{ mode: "*.*=SourceFile" }],
            uploadSettings: {
                actionUrl: '/destination_url',
                redirectUrl: '/redirect_url'
            }
        });
        uploader.writeHtml();
    </script>
</body>
</html>

The same server file processing code should work fine with both uploaders.

See Also

Reference

Manual