summaryrefslogtreecommitdiffstats
path: root/apps/files
diff options
context:
space:
mode:
Diffstat (limited to 'apps/files')
-rw-r--r--apps/files/js/file-upload.js141
-rw-r--r--apps/files/js/filelist.js20
2 files changed, 116 insertions, 45 deletions
diff --git a/apps/files/js/file-upload.js b/apps/files/js/file-upload.js
index 0d45623ce65..3242ae7fa6b 100644
--- a/apps/files/js/file-upload.js
+++ b/apps/files/js/file-upload.js
@@ -18,7 +18,7 @@
* - TODO music upload button
*/
-/* global jQuery, humanFileSize */
+/* global jQuery, humanFileSize, md5 */
/**
* File upload object
@@ -34,6 +34,8 @@
OC.FileUpload = function(uploader, data) {
this.uploader = uploader;
this.data = data;
+ var path = OC.joinPaths(this.uploader.fileList.getCurrentDirectory(), this.getFile().name);
+ this.id = 'web-file-upload-' + md5(path) + '-' + (new Date()).getTime();
};
OC.FileUpload.CONFLICT_MODE_DETECT = 0;
OC.FileUpload.CONFLICT_MODE_OVERWRITE = 1;
@@ -41,6 +43,13 @@ OC.FileUpload.CONFLICT_MODE_AUTORENAME = 2;
OC.FileUpload.prototype = {
/**
+ * Unique upload id
+ *
+ * @type string
+ */
+ id: null,
+
+ /**
* Upload element
*
* @type Object
@@ -67,6 +76,15 @@ OC.FileUpload.prototype = {
_newName: null,
/**
+ * Returns the unique upload id
+ *
+ * @return string
+ */
+ getId: function() {
+ return this.id;
+ },
+
+ /**
* Returns the file to be uploaded
*
* @return {File} file
@@ -143,6 +161,7 @@ OC.FileUpload.prototype = {
* Submit the upload
*/
submit: function() {
+ var self = this;
var data = this.data;
var file = this.getFile();
@@ -192,19 +211,54 @@ OC.FileUpload.prototype = {
}
}
+ var chunkFolderPromise;
+ if ($.support.blobSlice
+ && this.uploader.fileUploadParam.maxChunkSize
+ && this.getFile().size > this.uploader.fileUploadParam.maxChunkSize
+ ) {
+ data.isChunked = true;
+ chunkFolderPromise = this.uploader.davClient.createDirectory(
+ 'uploads/' + encodeURIComponent(OC.getCurrentUser().uid) + '/' + encodeURIComponent(this.getId())
+ );
+ // TODO: if fails, it means same id already existed, need to retry
+ } else {
+ chunkFolderPromise = $.Deferred().resolve().promise();
+ }
+
// wait for creation of the required directory before uploading
- folderPromise.then(function() {
+ $.when(folderPromise, chunkFolderPromise).then(function() {
data.submit();
}, function() {
- data.abort();
+ self.abort();
});
},
/**
+ * Process end of transfer
+ */
+ done: function() {
+ if (!this.data.isChunked) {
+ return $.Deferred().resolve().promise();
+ }
+
+ var uid = OC.getCurrentUser().uid;
+ return this.uploader.davClient.move(
+ 'uploads/' + encodeURIComponent(uid) + '/' + encodeURIComponent(this.getId()) + '/.file',
+ 'files/' + encodeURIComponent(uid) + '/' + OC.joinPaths(this.getFullPath(), this.getFileName())
+ );
+ },
+
+ /**
* Abort the upload
*/
abort: function() {
+ if (this.data.isChunked) {
+ // delete transfer directory for this upload
+ this.uploader.davClient.remove(
+ 'uploads/' + encodeURIComponent(OC.getCurrentUser().uid) + '/' + encodeURIComponent(this.getId())
+ );
+ }
this.data.abort();
},
@@ -280,7 +334,7 @@ OC.Uploader = function() {
this.init.apply(this, arguments);
};
-OC.Uploader.prototype = {
+OC.Uploader.prototype = _.extend({
/**
* @type Array<OC.FileUpload>
*/
@@ -384,7 +438,7 @@ OC.Uploader.prototype = {
self.filesClient.createDirectory(fullPath).always(function(status) {
// 405 is expected if the folder already exists
if ((status >= 200 && status < 300) || status === 405) {
- self.$uploadEl.trigger($.Event('fileuploadcreatedfolder'), fullPath);
+ self.trigger('createdfolder', fullPath);
deferred.resolve();
return;
}
@@ -407,8 +461,8 @@ OC.Uploader.prototype = {
submitUploads: function(uploads) {
var self = this;
_.each(uploads, function(upload) {
- upload.submit();
self._uploads[upload.data.uploadId] = upload;
+ upload.submit();
});
},
@@ -611,16 +665,6 @@ OC.Uploader.prototype = {
this.$uploadEl.trigger(new $.Event('resized'));
},
- on: function() {
- // forward events to upload element
- this.$uploadEl.on.apply(this.$uploadEl, arguments);
- },
-
- off: function() {
- // forward events to upload element
- this.$uploadEl.off.apply(this.$uploadEl, arguments);
- },
-
/**
* Returns whether the given file is known to be a received shared file
*
@@ -655,6 +699,12 @@ OC.Uploader.prototype = {
this.fileList = options.fileList;
this.filesClient = options.filesClient || OC.Files.getClient();
+ this.davClient = new OC.Files.Client({
+ host: OC.getHost(),
+ port: OC.getPort(),
+ root: OC.getRootPath() + '/remote.php/dav/',
+ useHTTPS: OC.getProtocol() === 'https'
+ });
$uploadEl = $($uploadEl);
this.$uploadEl = $uploadEl;
@@ -669,6 +719,7 @@ OC.Uploader.prototype = {
dropZone: options.dropZone, // restrict dropZone to content div
autoUpload: false,
sequentialUploads: true,
+ maxChunkSize: 10000000,
//singleFileUploads is on by default, so the data.files array will always have length 1
/**
* on first add of every selection
@@ -692,7 +743,7 @@ OC.Uploader.prototype = {
var upload = new OC.FileUpload(self, data);
// can't link directly due to jQuery not liking cyclic deps on its ajax object
- data.uploadId = _.uniqueId('file-upload');
+ data.uploadId = upload.getId();
// we need to collect all data upload objects before
// starting the upload so we can check their existence
@@ -842,7 +893,10 @@ OC.Uploader.prototype = {
},
fail: function(e, data) {
var upload = self.getUpload(data);
- var status = upload.getResponseStatus();
+ var status = null;
+ if (upload) {
+ status = upload.getResponseStatus();
+ }
self.log('fail', e, upload);
if (data.textStatus === 'abort') {
@@ -914,10 +968,7 @@ OC.Uploader.prototype = {
// add progress handlers
fileupload.on('fileuploadadd', function(e, data) {
self.log('progress handle fileuploadadd', e, data);
- //show cancel button
- //if (data.dataType !== 'iframe') { //FIXME when is iframe used? only for ie?
- // $('#uploadprogresswrapper .stop').show();
- //}
+ self.trigger('add', e, data);
});
// add progress handlers
fileupload.on('fileuploadstart', function(e, data) {
@@ -933,10 +984,12 @@ OC.Uploader.prototype = {
+ '</span></em>');
$('#uploadprogressbar').tipsy({gravity:'n', fade:true, live:true});
self._showProgressBar();
+ self.trigger('start', e, data);
});
fileupload.on('fileuploadprogress', function(e, data) {
self.log('progress handle fileuploadprogress', e, data);
//TODO progressbar in row
+ self.trigger('progress', e, data);
});
fileupload.on('fileuploadprogressall', function(e, data) {
self.log('progress handle fileuploadprogressall', e, data);
@@ -999,6 +1052,7 @@ OC.Uploader.prototype = {
})
);
$('#uploadprogressbar').progressbar('value', progress);
+ self.trigger('progressall', e, data);
});
fileupload.on('fileuploadstop', function(e, data) {
self.log('progress handle fileuploadstop', e, data);
@@ -1012,6 +1066,7 @@ OC.Uploader.prototype = {
if (data.errorThrown === 'abort') {
self._hideProgressBar();
}
+ self.trigger('fail', e, data);
});
var disableDropState = function() {
$('#app-content').removeClass('file-drag');
@@ -1046,22 +1101,36 @@ OC.Uploader.prototype = {
filerow.find('.thumbnail').addClass('icon-filetype-folder-drag-accept');
}
});
- fileupload.on('fileuploaddragleave fileuploaddrop', disableDropState);
- } else {
- // for all browsers that don't support the progress bar
- // IE 8 & 9
-
- // show a spinner
- fileupload.on('fileuploadstart', function() {
- $('#upload').addClass('icon-loading');
- $('#upload .icon-upload').hide();
+ fileupload.on('fileuploaddragleave fileuploaddrop', function (){
+ $('#app-content').removeClass('file-drag');
+ $('.dropping-to-dir').removeClass('dropping-to-dir');
+ $('.dir-drop').removeClass('dir-drop');
+ $('.icon-filetype-folder-drag-accept').removeClass('icon-filetype-folder-drag-accept');
});
- // hide a spinner
- fileupload.on('fileuploadstop fileuploadfail', function() {
- $('#upload').removeClass('icon-loading');
- $('#upload .icon-upload').show();
+ fileupload.on('fileuploadchunksend', function(e, data) {
+ // modify the request to adjust it to our own chunking
+ var upload = self.getUpload(data);
+ var range = data.contentRange.split(' ')[1];
+ var chunkId = range.split('/')[0];
+ data.url = OC.getRootPath() +
+ '/remote.php/dav/uploads' +
+ '/' + encodeURIComponent(OC.getCurrentUser().uid) +
+ '/' + encodeURIComponent(upload.getId()) +
+ '/' + encodeURIComponent(chunkId);
+ delete data.contentRange;
+ delete data.headers['Content-Range'];
});
+ fileupload.on('fileuploaddone', function(e, data) {
+ var upload = self.getUpload(data);
+ upload.done().then(function() {
+ self.trigger('done', e, upload);
+ });
+ });
+ fileupload.on('fileuploaddrop', function(e, data) {
+ self.trigger('drop', e, data);
+ });
+
}
}
@@ -1079,6 +1148,6 @@ OC.Uploader.prototype = {
return this.fileUploadParam;
}
-};
+}, OC.Backbone.Events);
diff --git a/apps/files/js/filelist.js b/apps/files/js/filelist.js
index 43cb3bac64b..2d6bca80f1a 100644
--- a/apps/files/js/filelist.js
+++ b/apps/files/js/filelist.js
@@ -2661,16 +2661,18 @@
/**
* Setup file upload events related to the file-upload plugin
+ *
+ * @param {OC.Uploader} uploader
*/
- setupUploadEvents: function($uploadEl) {
+ setupUploadEvents: function(uploader) {
var self = this;
self._uploads = {};
// detect the progress bar resize
- $uploadEl.on('resized', this._onResize);
+ uploader.on('resized', this._onResize);
- $uploadEl.on('fileuploaddrop', function(e, data) {
+ uploader.on('drop', function(e, data) {
self._uploader.log('filelist handle fileuploaddrop', e, data);
if (self.$el.hasClass('hidden')) {
@@ -2734,7 +2736,7 @@
}
}
});
- $uploadEl.on('fileuploadadd', function(e, data) {
+ uploader.on('add', function(e, data) {
self._uploader.log('filelist handle fileuploadadd', e, data);
// add ui visualization to existing folder
@@ -2766,16 +2768,16 @@
* when file upload done successfully add row to filelist
* update counter when uploading to sub folder
*/
- $uploadEl.on('fileuploaddone', function(e, data) {
+ uploader.on('done', function(e, upload) {
self._uploader.log('filelist handle fileuploaddone', e, data);
+ var data = upload.data;
var status = data.jqXHR.status;
if (status < 200 || status >= 300) {
// error was handled in OC.Uploads already
return;
}
- var upload = self._uploader.getUpload(data);
var fileName = upload.getFileName();
var fetchInfoPromise = self.addAndFetchFileInfo(fileName, upload.getFullPath());
if (!self._uploads) {
@@ -2785,10 +2787,10 @@
self._uploads[fileName] = fetchInfoPromise;
}
});
- $uploadEl.on('fileuploadcreatedfolder', function(e, fullPath) {
+ uploader.on('createdfolder', function(e, fullPath) {
self.addAndFetchFileInfo(OC.basename(fullPath), OC.dirname(fullPath));
});
- $uploadEl.on('fileuploadstop', function() {
+ uploader.on('stop', function() {
self._uploader.log('filelist handle fileuploadstop');
// prepare list of uploaded file names in the current directory
@@ -2804,7 +2806,7 @@
});
self.updateStorageStatistics();
});
- $uploadEl.on('fileuploadfail', function(e, data) {
+ uploader.on('fail', function(e, data) {
self._uploader.log('filelist handle fileuploadfail', e, data);
self._uploads = [];