Changing multiple file uploads to properly support iOS 6+
authorAlexander Ebert <ebert@woltlab.com>
Fri, 4 Oct 2013 17:41:46 +0000 (19:41 +0200)
committerAlexander Ebert <ebert@woltlab.com>
Fri, 4 Oct 2013 17:41:46 +0000 (19:41 +0200)
wcfsetup/install/files/js/WCF.Attachment.js
wcfsetup/install/files/js/WCF.js
wcfsetup/install/files/lib/data/attachment/AttachmentAction.class.php
wcfsetup/install/files/lib/system/upload/UploadFile.class.php
wcfsetup/install/files/lib/system/upload/UploadHandler.class.php

index b17355fb91590bb495ad25547e4496016b7b7447..9b05e2862984753dd1a9b28fe44f19786e9bb8f2 100644 (file)
@@ -164,7 +164,7 @@ WCF.Attachment.Upload = WCF.Upload.extend({
         * @see WCF.Upload._success()
         */
        _success: function(uploadID, data) {
-               for (var $i = 0; $i < this._uploadMatrix[uploadID].length; $i++) {
+               for (var $i in this._uploadMatrix[uploadID]) {
                        // get li
                        var $li = this._uploadMatrix[uploadID][$i];
                        
@@ -173,10 +173,11 @@ WCF.Attachment.Upload = WCF.Upload.extend({
                        
                        // get filename and check result
                        var $filename = $li.data('filename');
-                       if (data.returnValues && data.returnValues['attachments'][$filename]) {
+                       var $internalFileID = $li.data('internalFileID');
+                       if (data.returnValues && data.returnValues.attachments[$internalFileID]) {
                                // show thumbnail
-                               if (data.returnValues['attachments'][$filename]['tinyURL']) {
-                                       $li.children('.icon-spinner').replaceWith($('<img src="' + data.returnValues['attachments'][$filename]['tinyURL'] + '" alt="" class="attachmentTinyThumbnail" />'));
+                               if (data.returnValues.attachments[$internalFileID]['tinyURL']) {
+                                       $li.children('.icon-spinner').replaceWith($('<img src="' + data.returnValues.attachments[$internalFileID]['tinyURL'] + '" alt="" class="attachmentTinyThumbnail" />'));
                                }
                                // show file icon
                                else {
@@ -185,23 +186,22 @@ WCF.Attachment.Upload = WCF.Upload.extend({
                                
                                // update attachment link
                                var $link = $('<a href=""></a>');
-                               $link.text($filename).attr('href', data.returnValues['attachments'][$filename]['url']);
+                               $link.text($filename).attr('href', data.returnValues.attachments[$internalFileID]['url']);
                                
-                               if (data.returnValues['attachments'][$filename]['isImage'] != 0) {
-                                       console.debug(data.returnValues['attachments'][$filename]['isImage']);
+                               if (data.returnValues.attachments[$internalFileID]['isImage'] != 0) {
                                        $link.addClass('jsImageViewer').attr('title', $filename);
                                }
                                $li.find('p').empty().append($link);
                                
                                // update file size
-                               $li.find('small').append(data.returnValues['attachments'][$filename]['formattedFilesize']);
+                               $li.find('small').append(data.returnValues.attachments[$internalFileID]['formattedFilesize']);
                                
                                // init buttons
-                               var $deleteButton = $('<li><span class="icon icon16 icon-remove pointer jsTooltip jsDeleteButton" title="'+WCF.Language.get('wcf.global.button.delete')+'" data-object-id="'+data.returnValues['attachments'][$filename]['attachmentID']+'" data-confirm-message="'+WCF.Language.get('wcf.attachment.delete.sure')+'" /></li>');
+                               var $deleteButton = $('<li><span class="icon icon16 icon-remove pointer jsTooltip jsDeleteButton" title="'+WCF.Language.get('wcf.global.button.delete')+'" data-object-id="'+data.returnValues.attachments[$internalFileID]['attachmentID']+'" data-confirm-message="'+WCF.Language.get('wcf.attachment.delete.sure')+'" /></li>');
                                $li.find('ul').append($deleteButton);
                                
                                if (this._wysiwygContainerID) {
-                                       var $insertButton = $('<li><span class="icon icon16 icon-paste pointer jsTooltip jsButtonInsertAttachment" title="' + WCF.Language.get('wcf.attachment.insert') + '" data-object-id="' + data.returnValues['attachments'][$filename]['attachmentID'] + '" /></li>');
+                                       var $insertButton = $('<li><span class="icon icon16 icon-paste pointer jsTooltip jsButtonInsertAttachment" title="' + WCF.Language.get('wcf.attachment.insert') + '" data-object-id="' + data.returnValues.attachments[$internalFileID]['attachmentID'] + '" /></li>');
                                        $insertButton.children('.jsButtonInsertAttachment').click($.proxy(this._insert, this));
                                        $li.find('ul').append($insertButton);
                                }
@@ -212,8 +212,8 @@ WCF.Attachment.Upload = WCF.Upload.extend({
                                var $errorMessage = '';
                                
                                // error handling
-                               if (data.returnValues && data.returnValues['errors'][$filename]) {
-                                       $errorMessage = data.returnValues['errors'][$filename]['errorType'];
+                               if (data.returnValues && data.returnValues.errors[$internalFileID]) {
+                                       $errorMessage = data.returnValues.errors[$internalFileID]['errorType'];
                                }
                                else {
                                        // unknown error
index 955ec19c91a76141aad2941fbdd78668b61814b8..ba4999f781edfffc46b01701aa77ee187a3d9a7b 100755 (executable)
@@ -6678,6 +6678,12 @@ WCF.Upload = Class.extend({
         */
        _iframe: null,
        
+       /**
+        * internal file id
+        * @var integer
+        */
+       _internalFileID: 0,
+       
        /**
         * additional options
         * @var jQuery
@@ -6714,6 +6720,7 @@ WCF.Upload = Class.extend({
                this._buttonSelector = buttonSelector;
                this._fileListSelector = fileListSelector;
                this._className = className;
+               this._internalFileID = 0;
                this._options = $.extend(true, {
                        action: 'upload',
                        multiple: false,
@@ -6781,17 +6788,10 @@ WCF.Upload = Class.extend({
                                return;
                        }
                        
-                       var $validFilenames = [ ];
-                       for (var $i = 0, $length = this._uploadMatrix[$uploadID].length; $i < $length; $i++) {
-                               var $li = this._uploadMatrix[$uploadID][$i];
-                               if (!$li.hasClass('uploadFailed')) {
-                                       $validFilenames.push($li.data('filename'));
-                               }
-                       }
-                       
                        for (var $i = 0, $length = $files.length; $i < $length; $i++) {
-                               if ($validFilenames.indexOf($files[$i].name) !== -1) {
-                                       $fd.append('__files[]', $files[$i]);
+                               if (this._uploadMatrix[$uploadID][$i]) {
+                                       var $internalFileID = this._uploadMatrix[$uploadID][$i].data('internalFileID');
+                                       $fd.append('__files[' + $internalFileID + ']', $files[$i]);
                                }
                        }
                        
@@ -6799,7 +6799,7 @@ WCF.Upload = Class.extend({
                        $fd.append('className', this._className);
                        var $additionalParameters = this._getParameters();
                        for (var $name in $additionalParameters) {
-                               $fd.append('parameters['+$name+']', $additionalParameters[$name]);
+                               $fd.append('parameters[' + $name + ']', $additionalParameters[$name]);
                        }
                        
                        var self = this;
@@ -6843,8 +6843,8 @@ WCF.Upload = Class.extend({
                                var $li = this._initFile($file);
                                
                                if (!$li.hasClass('uploadFailed')) {
-                                       $li.data('filename', $file.name);
-                                       this._uploadMatrix[$uploadID].push($li);
+                                       $li.data('filename', $file.name).data('internalFileID', this._internalFileID++);
+                                       this._uploadMatrix[$uploadID][$i] = $li;
                                }
                        }
                        
@@ -6880,7 +6880,7 @@ WCF.Upload = Class.extend({
        _progress: function(uploadID, event) {
                var $percentComplete = Math.round(event.loaded * 100 / event.total);
                
-               for (var $i = 0; $i < this._uploadMatrix[uploadID].length; $i++) {
+               for (var $i in this._uploadMatrix[uploadID]) {
                        this._uploadMatrix[uploadID][$i].find('progress').attr('value', $percentComplete);
                }
        },
index fe81958140a8bc30f42c98da08ea0f9e3aeb67eb..2312d37e3f2c134e208805cdcc0959cd7bc0be56 100644 (file)
@@ -173,7 +173,7 @@ class AttachmentAction extends AbstractDatabaseObjectAction {
                                        EventHandler::getInstance()->fireAction($this, 'checkThumbnail');
                                        if ($this->eventData['hasThumbnail']) $thumbnails[] = $attachment;
                                }
-                               $attachments[] = $attachment;
+                               $attachments[$file->getInternalFileID()] = $attachment;
                        }
                        else {
                                // moving failed; delete attachment
@@ -194,8 +194,11 @@ class AttachmentAction extends AbstractDatabaseObjectAction {
                $result = array('attachments' => array(), 'errors' => array());
                if (!empty($attachments)) {
                        // get attachment ids
-                       $attachmentIDs = array();
-                       foreach ($attachments as $attachment) $attachmentIDs[] = $attachment->attachmentID;
+                       $attachmentIDs = $attachmentToFileID = array();
+                       foreach ($attachments as $internalFileID => $attachment) {
+                               $attachmentIDs[] = $attachment->attachmentID;
+                               $attachmentToFileID[$attachment->attachmentID] = $internalFileID;
+                       }
                        
                        // get attachments from database (check thumbnail status)
                        $attachmentList = new AttachmentList();
@@ -203,7 +206,7 @@ class AttachmentAction extends AbstractDatabaseObjectAction {
                        $attachmentList->readObjects();
                        
                        foreach ($attachmentList as $attachment) {
-                               $result['attachments'][$attachment->filename] = array(
+                               $result['attachments'][$attachmentToFileID[$attachment->attachmentID]] = array(
                                        'filename' => $attachment->filename,
                                        'filesize' => $attachment->filesize,
                                        'formattedFilesize' => FileUtil::formatFilesize($attachment->filesize),
@@ -217,7 +220,7 @@ class AttachmentAction extends AbstractDatabaseObjectAction {
                }
                
                foreach ($failedUploads as $failedUpload) {
-                       $result['errors'][$failedUpload->getFilename()] = array(
+                       $result['errors'][$failedUpload->getInternalFileID()] = array(
                                'filename' => $failedUpload->getFilename(),
                                'filesize' => $failedUpload->getFilesize(),
                                'errorType' => $failedUpload->getValidationErrorType()
index f6b405a92533ce0e9c22ea48e7e60ec4e0d3df9e..4abed6f23559ce22a81f01307d96e0b4d336aa5c 100644 (file)
@@ -19,6 +19,12 @@ class UploadFile {
         */
        protected $filename = '';
        
+       /**
+        * internal file id
+        * @var integer
+        */
+       protected $internalFileID = 0;
+       
        /**
         * location of the uploaded file
         * @var string
@@ -59,6 +65,11 @@ class UploadFile {
         * @param       string          $mimeType
         */
        public function __construct($filename, $location, $filesize, $errorCode = 0, $mimeType = '') {
+               if (preg_match('~^__wcf_([0-9]+)_(.*)~', $filename, $matches)) {
+                       $this->internalFileID = $matches[1];
+                       $filename = $matches[2];
+               }
+               
                $this->filename = $filename;
                $this->location = $location;
                $this->filesize = $filesize;
@@ -75,6 +86,15 @@ class UploadFile {
                return $this->filename;
        }
        
+       /**
+        * Returns internal file id.
+        * 
+        * @return      integer
+        */
+       public function getInternalFileID() {
+               return $this->internalFileID;
+       }
+       
        /**
         * Returns the extension of the original file name.
         * 
index 605a3e5c8dbc25b5ce2c5748f3fe2a926df5611c..6d1a4d038a9604437fa1db862956d1bad51673e2 100644 (file)
@@ -32,6 +32,26 @@ class UploadHandler {
         */
        protected function __construct(array $rawFileData) {
                if (is_array($rawFileData['name'])) {
+                       // iOS work-around
+                       $newRawFileData = array(
+                               'name' => array(),
+                               'type' => array(),
+                               'tmp_name' => array(),
+                               'error' => array(),
+                               'size' => array()
+                       );
+                       $i = 0;
+                       foreach (array_keys($rawFileData['name']) as $internalFileID) {
+                               $newRawFileData['name'][$i] = '__wcf_' . $internalFileID . '_' . $rawFileData['name'][$internalFileID]; // __wcf_X_filename.ext
+                               $newRawFileData['type'][$i] = $rawFileData['type'][$internalFileID];
+                               $newRawFileData['tmp_name'][$i] = $rawFileData['tmp_name'][$internalFileID];
+                               $newRawFileData['error'][$i] = $rawFileData['error'][$internalFileID];
+                               $newRawFileData['size'][$i] = $rawFileData['size'][$internalFileID];
+                               
+                               $i++;
+                       }
+                       $rawFileData = $newRawFileData;
+                       
                        // multiple uploads
                        for ($i = 0, $l = count($rawFileData['name']); $i < $l; $i++) {
                                $this->files[] = new UploadFile($rawFileData['name'][$i], $rawFileData['tmp_name'][$i], $rawFileData['size'][$i], $rawFileData['error'][$i], ($rawFileData['tmp_name'][$i] ? (FileUtil::getMimeType($rawFileData['tmp_name'][$i]) ?: $rawFileData['type'][$i]) : ''));