Extension:jQueryUpload

From Organic Design wiki
Info.svg This code is in our Git repository here.

Note: If there is no information in this page about this code and it's a MediaWiki extension, there may be something at mediawiki.org.

A job I was working on required jQuery file uploads into the wiki using the "attach file" link and also directly into Ajax comments. But they required that the files be able to be renamed before uploading, so I needed to modify the upload code slightly. Changing the filename part into an input box was simply a matter of changing template-upload (which is index.html in the demo code), but processing the PHP side was more difficult since there can be many files uploading at once and they can upload in chunks.

The initial test worked for single non-chunked files which is simply to adjust server/php/index.php to overwrite the name in the $_FILES array with the new name from the input box added to the form called upload_rename_file.

$_FILES['files']['name'][0] = $_REQUEST['upload_rename_file'];


Screen shot of the added form field

File-upload-rename.jpg

Working implementation

The following method works for multiple files and chunks. It's done by posting the rename data as two arrays, one of the original names and one of the new names. These arrays are posted along with each file or chunk so that the PHP can use the original name to find which new name the file or chunk should be renamed to.

First this modification is made to template-upload which adds a hidden input to populate the posted array of original filename data, and changes the displayed text name to a text input with the extension removed and added after the input so it can't be accidentally removed or modified.

<input type="hidden" name="upload_rename_from[]" value="{%=file.name%}" />
<input type="text" name="upload_rename_to[]" value="{%=uploadRenameBase(file.name)%}" />
{%=uploadRenameExt(file.name)%}


Then this JavaScript is added to the end of the HTML containing the upload form in its own script element which returns the main part of the filename and the extension part, and are called by the template above.

function uploadRenameBase(name) {
    var re = /^(.+)(\..+?)$/;
    var m = re.exec(name);
    return m[1];
}
function uploadRenameExt(name) {
    var re = /^(.+)(\..+?)$/;
    var m = re.exec(name);
    return m[2];
}


Finally, the main part is the PHP which is at the very start of the form processing script. It first checks if any renaming data is being posted, and if so it scans through the original names array and checks if there's any uploading files with the same name, and if so changes the name to the equivalent entry in the new names array.

if( array_key_exists( 'upload_rename_from', $_REQUEST ) && array_key_exists( 'files', $_FILES ) ) {
    foreach( $_REQUEST['upload_rename_from'] as $i => $from ) {
        if( false !== $j = array_search( $from, $_FILES['files']['name'] ) ) {
            $ext = pathinfo( $from, PATHINFO_EXTENSION );
            $_FILES['files']['name'][$j] = $_REQUEST['upload_rename_to'][$i] . ".$ext"; 
        }
    }
}

Adding extra information to uploaded file items

Another modification we needed to do was to add information to the items in the list of uploaded files showing the user who uploaded the file and the date it was uploaded. This was done by overriding the get_file_object method to add to extra properties, and modifying the download template to add the extra information.

File icons

We need this to work mainly for PDF files, word documents and Excel spreadsheets, rather than images. The program currently doesn't have any file-extension based icon system which we need for ours, so this section describes how the program can be modified to allow custom icons.

This has been done now, and uses the Farm Fresh Web Icons or if nothing is selected, then MediaWiki's own file icons are used, but these are a bit too big.

JQueryUploadIcons.jpg

Wiki integration

We want this to work in such as way that there's never any reason to leave the page when adding comments or uploading files. Files can be upload within the context of a comment, or in the context of the whole page. When clicking on the "attach file" link in one of these areas, any other areas file-upload area will be hidden, and the newly clicked file-upload area revealed or populated by a request requested from the server.

The files shown by the upload-module will be only those already uploaded to the current file-upload area, so each page and area within a page are a specific file-system directory.

Later the system may be extended to integrate with the wiki's uploaded files and page-source for attachments, but we'll start with a version that deals with its own directories separate from the wiki's images directory. The job that this project is being done for won't be using uploaded files for any purpose other than attaching documents to individual articles and comments within those articles, so there's no need to complicate things by trying to integrate to a deeper level than necessary.

A test extension has been made called jQueryUpload which creates a special page for uploading file into the wiki using the module. It works with file protection enabled, and uses the Farm Fresh Web Icons for file icons and falls back on the ones that come with MediaWiki by symlinking to them from its thumbnails directory.

The wiki integration has been done now. It works by allowing the upload module to have an extra parameter for storing files in sub-directories of the files directory and then the form uses the article ID as the sub-directory.

JQueryUploadAttach.jpg

Security

Another issue that needs to be dealt with is that the files should not be available to anonymous users, so we need to store the files outside of web-space and then use readfile to return the content if the user is logged in.

The first step to achieving this would be to change the PHP form processor into a MediaWiki Ajax handler so that the user properties are available.

See also