Skip to content

Uploader

The Uploader provides the ability to upload files in Cloudrexx through an easy and intuitive user interface. It supports drag&drop file selection and previews queued images.

The new uploader modal

Integration

Basic

  1. Create a new instance of \Cx\Core_Modules\Uploader\Model\Entity\Uploader in your code. This should normally be done within the Frontend- or BackendController.
  2. Directly set an upload target destination path using option target-path or implement a server-side callback-handler.
  3. Use Uploader::getXHtml() to fetch the generated HTML-input-code and put it into your template using Sigma::setVariable()

Example code for modules/<component>/Controller/BackendController.class.php

This example uses the \Cx\Core_Modules\Uploader\Model\DefaultUploadCallback class as a server-side callback-handler which will upload the files into the folder /image/content/ of the Cloudrexx instance.

public function parsePage(\Cx\Core\Html\Sigma $template, array $cmd, &$isSingle = false) {
    $uploader = new \Cx\Core_Modules\Uploader\Model\Entity\Uploader();
    $uploader->setFinishedCallback(
        '\Cx\Core_Modules\Uploader\Model\DefaultUploadCallback'
    );
    $template->setVariable(
        // Placeholder in the template
        'UPLOADER_CODE',
        // Fetch HTML-button-element
        // The passed argument is used as label of the button element
        $uploader->getXHtml('Open Uploader')
    );
}

Example code for modules/<component>/View/Template/Backend/Default.html

{UPLOADER_CODE}

Folder Widget

Use the FolderWidget to interactively display the uploaded files before the server-side callback is being triggered.

Implement as follows:

$folderWidget = new \Cx\Core_Modules\MediaBrowser\Model\Entity\FolderWidget($pathToFolder);

Use FolderWidget::getXHtml() to fetch the HTML-code to insert into your Sigma template:

1
2
3
$template->setVariable(array(
    'FOLDER_WIDGET_CODE' => $folderWidget->getXHtml(),
));

Update file list

To update the file list of the FolderWidget do register a client-side callback as follows:

1
2
3
4
5
6
7
$uploader->setCallback('JsCallback');
$cxJs = \ContrexxJavascript::getInstance();
$cxJs->setVariable(
    'FolderWidgetId',
    $folderWidget->getId(),
    'MyComponent'
);

Then update the file list in JavaScript as follows:

1
2
3
function JsCallback(callback) {
    angular.element('#mediaBrowserfolderWidget_' + cx.variables.get('FolderWidgetId', 'MyComponent')).scope().refreshBrowser();
}

By default, the Uploader will be opened in a modal window. However, it is possible to integrate the Uploader as an inline widget. To do so, do change the type as follows:

$uploader->setType(\Cx\Core_Modules\Uploader\Model\Entity\Uploader::UPLOADER_TYPE_INLINE);

Button customization

Customize the layout of the HTML-button-element by setting any valid button-attribute:

1
2
3
4
5
6
7
// set html attributes for styling or javascript
$uploader->setOptions(
    array(
        'id' => 'page_target_browse',
        'type' => 'button'
    )
);

Or add additional CSS classes as follows:

$uploader->addClass('fancy-button');

Image preview

When the Uploader is being used as an image selector, then it can be set up with a real-time image preview functionality on a selected HTML-img element:

1
2
3
4
5
$uploader->setOptions(array(
    'data-thumb-selector' => '#img-preview',
    'data-thumb-max-width' => 120,
    'data-thumb-max-height' => 120,
));

Explanation of options:

Option name Description
data-thumb-selector jQuery selector to identify the HTML-img element on which the selected image shall be previewed.
data-thumb-max-width Width of the preview image
data-thumb-max-height Height of the preview image

Resume existing session

To resume an existing upload session, do pass the ID of the upload session as argument on object instantiation:

$uploader = \Cx\Core_Modules\Uploader\Model\Entity\Uploader($id);

The ID of an existing upload session is available through Uploader::getId()

$id = $uploader->getId();

Use Uploader::isValidId() to verify an ID's validity:

1
2
3
if (!\Cx\Core_Modules\Uploader\Model\Entity\Uploader::isValidId($id)) {
    throw new \Exception('Invalid ID');
}

Drop session

To clean up the user session after a successful upload, completed upload sessions can be dropped as follows:

\Cx\Core_Modules\Uploader\Model\Entity\Uploader::destroy($id);

Callback handling

Server-side (PHP)

Use server-side callback-handling to manually process & move the uploaded files into the desired target location.

To specify a callback you can provide a class which implements \Cx\Core_Modules\Uploader\Model\UploadCallbackInterface.

1
2
3
$uploader->setFinishedCallback(
    '\Cx\Core_Modules\Uploader\Model\DefaultUploadCallback'
);

When the upload is finished the Uploader will call the uploadFinished() method of the class with the specified arguments in the UploadCallbackInterface interface.

/**
 * @param $tempPath String Path to the temporary directory containing the files at this moment.
 * @param $tempWebPath String Points to the same folder as tempPath, but relative to the webroot.
 * @param $data String Data given to setData() when creating the uploader.
 * @param $uploadId integer Per-session unique id for the current upload.
 * @param $fileInfos array('originalFileNames' => array( 'theCurrentAndCleanedFilename.txt' => 'raw!Source#Filename.txt' ) )
 *
 * @return mixed The return value can be an array as shown in the example or null.
 *               When returning an array, all files left in the temporary directory are moved accordingly.
 *               When returning null, all left files are deleted.
 */
function uploadFinished($tempPath, $tempWebPath, $data, $uploadId, $fileInfos, $response);

You can find a example for a callback in the \Cx\Core_Modules\Uploader\Model\DefaultUploadCallback class. The Uploader injects the \Cx\Core\Core\Controller\Cx instance as a first parameter in the contructor so we don't have to use singeltons or global objects.

The method uploadFinished() should return an array with the location where the uploaded file(s) should be moved to. The array must have the follwing structure:

1
2
3
4
[
    '/absolute/file/system/path/to/target/path',
    '/relative/web/path/to/target/path',
]

Pass additional data arguments

To pass additional data to the server-side callback method, do set them through Uploader::setData():

1
2
3
$uploader->setData(array(
    'foo' => 'bar'
));

The data can then be accessed through the $data argument in the callback method:

1
2
3
4
5
6
function uploadFinished($tempPath, $tempWebPath, $data, $uploadId, $fileInfos, $response){
   // array(1) {
   //     "foor"]=> string(3) "bar"
   // }
   var_dump($data)
}

Client-side (JavaScript)

The Uploader will call a specified JavaScript callback after the upload has finished and the user has closed the Uploader's modal window. The function should be available from the global window context. This function will also be called with an empty array if the user hasn't uploaded anything.

Register JavaScript callback from PHP:

1
2
3
// Function attached to window which gets called when the
// upload window is closed after an successful upload.
$uploader->setCallback('gallery.afterUpload');

Define JavaScript callback in JavaScript:

1
2
3
4
5
window.gallery = {
    afterUpload: function(files){
        // The files array contains all uploaded files
    }
}

The first argument passed to the javascript callback is the array with the uploaded files. I.e.:

1
2
3
4
["/images/content/Screenshot-from-2014-10-01-114138.png", 
 "/images/content/Screenshot-from-2014-10-01-153505.png", 
 "/images/content/Screenshot-from-2014-10-01-162041.png",
 "/images/content/Screenshot-from-2014-10-03-134226.png"]

Configuration

Upload Target Path

As an alternative on using a server-side Callback for manually moving the uploaded files into the target destination path, a direct upload target path can be specified using the option target-path:

1
2
3
$uploader->setOptions(array(
    'target-path' => '/absolute/path/to/a/MediaSource',
));

File count limit

You can specify how many files the user can upload by using the method Uploader::setUploadLimit():

$uploader->setUploadLimit(1);

File size limit

Restrict the upload to a maximum file size limit. The method accepts numeric or formatted string values, e.g.: 204800 or "204800b" or "200kb".

$uploader->setMaxFileSize('10mb');

File extension restriction

Restrict the set of allowed file extensions to be uploaded through option allowed-extensions:

1
2
3
$uploader->setOptions(array(
    'allowed-extensions' => array('jpg', 'jpeg', 'png', 'gif')
));

Technical Notes

Security

All files are primaraly being uploaded into a temporary session storage which is not accessible over HTTP(S). From there the files are either automatically being moved into the target upload path (if option target-path is set) or manually using a server-side callback-hanlder.

Note

Before files are added to the temporary session storage, their file names are sanitized as follows:

  • Umlauts are transliterated
  • Whitespace and non-latin characters are replaced by _
  • Names are truncated to a maximum length of 255 characters
  • If the file extension is missing or is one of the following, the extension .txt will be attached:
    • exe, bat, pif, com, vs, vbs, php, php4, php5, phps, cgi, pl, jsp, jspx, asp, aspx, jsp, jspx, jhtml, phtml, cfm, htaccess,py
    • If option Allow upload of client-side scripts is disabled (under Administration > Global Configuration > System > Security): xhtml, xml, svg, shtml

Garbage Collection

Partially (incomplete) uploaded files are automatically flushed from the temporary session storage once they are older than 5 hours.