diff options
author | Vincent Petry <pvince81@owncloud.com> | 2016-09-09 12:19:29 +0200 |
---|---|---|
committer | Roeland Jago Douma <roeland@famdouma.nl> | 2016-11-02 22:15:03 +0100 |
commit | 6a4ea2c15adb254291b095cfe21818aa28c26138 (patch) | |
tree | ef9a606eb82f486254126118ebde6a9851d30888 /apps/files/js/file-upload.js | |
parent | c1feae1684934bb52b1edaa67d33d01b377b875a (diff) | |
download | nextcloud-server-6a4ea2c15adb254291b095cfe21818aa28c26138.tar.gz nextcloud-server-6a4ea2c15adb254291b095cfe21818aa28c26138.zip |
Upload autorename on client side
Removes the need for POST to collection which would hit against upload
limits.
The client tries to auto rename the file by adding a suffix "(2)".
It tries to use the file list on the client side to guess a
suitable name. In case a file still cannot be uploaded and creates a
conflict, which can happen when the file was concurrently uploaded, the
logic will continue increasing the suffix.
Diffstat (limited to 'apps/files/js/file-upload.js')
-rw-r--r-- | apps/files/js/file-upload.js | 85 |
1 files changed, 54 insertions, 31 deletions
diff --git a/apps/files/js/file-upload.js b/apps/files/js/file-upload.js index 18d0d973586..8bcaa2e24aa 100644 --- a/apps/files/js/file-upload.js +++ b/apps/files/js/file-upload.js @@ -100,26 +100,14 @@ OC.FileUpload.prototype = { /** * Return the final filename. - * Either this is the original file name or the file name - * after an autorename. * * @return {String} file name */ getFileName: function() { - // in case of autorename + // autorenamed name if (this._newName) { return this._newName; } - - if (this._conflictMode === OC.FileUpload.CONFLICT_MODE_AUTORENAME) { - - var locationUrl = this.getResponseHeader('Content-Location'); - if (locationUrl) { - this._newName = decodeURIComponent(OC.basename(locationUrl)); - return this._newName; - } - } - return this.getFile().name; }, @@ -142,8 +130,19 @@ OC.FileUpload.prototype = { }, /** + * Returns conflict resolution mode. + * + * @return {int} conflict mode + */ + getConflictMode: function() { + return this._conflictMode || OC.FileUpload.CONFLICT_MODE_DETECT; + }, + + /** * Set conflict resolution mode. * See CONFLICT_MODE_* constants. + * + * @param {int} mode conflict mode */ setConflictMode: function(mode) { this._conflictMode = mode; @@ -163,6 +162,30 @@ OC.FileUpload.prototype = { }, /** + * Trigger autorename and append "(2)". + * Multiple calls will increment the appended number. + */ + autoRename: function() { + var name = this.getFile().name; + if (!this._renameAttempt) { + this._renameAttempt = 1; + } + + var dotPos = name.lastIndexOf('.'); + var extPart = ''; + if (dotPos > 0) { + this._newName = name.substr(0, dotPos); + extPart = name.substr(dotPos); + } else { + this._newName = name; + } + + // generate new name + this._renameAttempt++; + this._newName = this._newName + ' (' + this._renameAttempt + ')' + extPart; + }, + + /** * Submit the upload */ submit: function() { @@ -179,7 +202,7 @@ OC.FileUpload.prototype = { } if (this.uploader.fileList) { - this.data.url = this.uploader.fileList.getUploadUrl(file.name, this.getFullPath()); + this.data.url = this.uploader.fileList.getUploadUrl(this.getFileName(), this.getFullPath()); } if (!this.data.headers) { @@ -191,12 +214,9 @@ OC.FileUpload.prototype = { this.data.type = 'PUT'; delete this.data.headers['If-None-Match']; - if (this._conflictMode === OC.FileUpload.CONFLICT_MODE_DETECT) { + if (this._conflictMode === OC.FileUpload.CONFLICT_MODE_DETECT + || this._conflictMode === OC.FileUpload.CONFLICT_MODE_AUTORENAME) { this.data.headers['If-None-Match'] = '*'; - } else if (this._conflictMode === OC.FileUpload.CONFLICT_MODE_AUTORENAME) { - // POST to parent folder, with slug - this.data.type = 'POST'; - this.data.url = this.uploader.fileList.getUploadUrl('&' + file.name, this.getFullPath()); } if (file.lastModified) { @@ -212,18 +232,6 @@ OC.FileUpload.prototype = { 'Basic ' + btoa(userName + ':' + (password || '')); } - if (!this.uploader.isXHRUpload()) { - data.formData = []; - - // pass headers as parameters - data.formData.push({name: 'headers', value: JSON.stringify(this.data.headers)}); - data.formData.push({name: 'requesttoken', value: OC.requestToken}); - if (data.type === 'POST') { - // still add the method to the URL - data.url += '?_method=POST'; - } - } - var chunkFolderPromise; if ($.support.blobSlice && this.uploader.fileUploadParam.maxChunkSize @@ -491,6 +499,14 @@ OC.Uploader.prototype = _.extend({ //show "file already exists" dialog var self = this; var file = fileUpload.getFile(); + // already attempted autorename but the server said the file exists ? (concurrently added) + if (fileUpload.getConflictMode() === OC.FileUpload.CONFLICT_MODE_AUTORENAME) { + // attempt another autorename, defer to let the current callback finish + _.defer(function() { + self.onAutorename(fileUpload); + }); + return; + } // retrieve more info about this file this.filesClient.getFileInfo(fileUpload.getFullPath()).then(function(status, fileInfo) { var original = fileInfo; @@ -603,6 +619,13 @@ OC.Uploader.prototype = _.extend({ onAutorename:function(upload) { this.log('autorename', null, upload); upload.setConflictMode(OC.FileUpload.CONFLICT_MODE_AUTORENAME); + + do { + upload.autoRename(); + // if file known to exist on the client side, retry + } while (this.fileList && this.fileList.inList(upload.getFileName())); + + // resubmit upload this.submitUploads([upload]); }, _trace:false, //TODO implement log handler for JS per class? |