Merge pull request #14140 from edx/mushtaq/video-upload-restrict
Video upload restrictions
This commit is contained in:
@@ -10,13 +10,15 @@ define([
|
||||
concurrentUploadLimit,
|
||||
uploadButton,
|
||||
previousUploads,
|
||||
videoSupportedFileFormats
|
||||
videoSupportedFileFormats,
|
||||
videoUploadMaxFileSizeInGB
|
||||
) {
|
||||
var activeView = new ActiveVideoUploadListView({
|
||||
postUrl: videoHandlerUrl,
|
||||
concurrentUploadLimit: concurrentUploadLimit,
|
||||
uploadButton: uploadButton,
|
||||
videoSupportedFileFormats: videoSupportedFileFormats,
|
||||
videoUploadMaxFileSizeInGB: videoUploadMaxFileSizeInGB,
|
||||
onFileUploadDone: function(activeVideos) {
|
||||
$.ajax({
|
||||
url: videoHandlerUrl,
|
||||
|
||||
@@ -18,16 +18,16 @@ define(
|
||||
this.postUrl = '/test/post/url';
|
||||
this.uploadButton = $('<button>');
|
||||
this.videoSupportedFileFormats = ['.mp4', '.mov'];
|
||||
this.videoUploadMaxFileSizeInGB = 5;
|
||||
this.view = new ActiveVideoUploadListView({
|
||||
concurrentUploadLimit: concurrentUploadLimit,
|
||||
postUrl: this.postUrl,
|
||||
uploadButton: this.uploadButton,
|
||||
videoSupportedFileFormats: this.videoSupportedFileFormats
|
||||
videoSupportedFileFormats: this.videoSupportedFileFormats,
|
||||
videoUploadMaxFileSizeInGB: this.videoUploadMaxFileSizeInGB
|
||||
});
|
||||
this.view.render();
|
||||
jasmine.Ajax.install();
|
||||
this.globalAjaxError = jasmine.createSpy();
|
||||
$(document).ajaxError(this.globalAjaxError);
|
||||
});
|
||||
|
||||
// Remove window unload handler triggered by the upload requests
|
||||
@@ -89,6 +89,38 @@ define(
|
||||
});
|
||||
});
|
||||
|
||||
describe('Upload file', function() {
|
||||
_.each(
|
||||
[
|
||||
{desc: 'larger than', additionalBytes: 1},
|
||||
{desc: 'equal to', additionalBytes: 0},
|
||||
{desc: 'smaller than', additionalBytes: - 1}
|
||||
],
|
||||
function(caseInfo) {
|
||||
it(caseInfo.desc + 'max file size', function() {
|
||||
var maxFileSizeInBytes = this.view.getMaxFileSizeInBytes(),
|
||||
fileSize = maxFileSizeInBytes + caseInfo.additionalBytes,
|
||||
fileToUpload = {
|
||||
files: [
|
||||
{name: 'file.mp4', size: fileSize}
|
||||
]
|
||||
};
|
||||
this.view.$uploadForm.fileupload('add', fileToUpload);
|
||||
if (fileSize > maxFileSizeInBytes) {
|
||||
expect(this.view.fileErrorMsg).toBeDefined();
|
||||
expect(this.view.fileErrorMsg.options.title).toEqual('Your file could not be uploaded');
|
||||
expect(this.view.fileErrorMsg.options.message).toEqual(
|
||||
'file.mp4 exceeds maximum size of ' + this.videoUploadMaxFileSizeInGB + ' GB.'
|
||||
);
|
||||
} else {
|
||||
this.view.$uploadForm.fileupload('add', fileToUpload);
|
||||
expect(this.view.fileErrorMsg).toBeNull();
|
||||
}
|
||||
});
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
_.each(
|
||||
[
|
||||
{desc: 'a single file', numFiles: 1},
|
||||
@@ -122,21 +154,25 @@ define(
|
||||
});
|
||||
|
||||
it('should trigger the correct request', function() {
|
||||
expect(this.request.url).toEqual(this.postUrl);
|
||||
expect(this.request.method).toEqual('POST');
|
||||
expect(this.request.requestHeaders['Content-Type']).toEqual('application/json');
|
||||
expect(this.request.requestHeaders['Accept']).toContain('application/json');
|
||||
expect(JSON.parse(this.request.params)).toEqual({
|
||||
'files': _.map(
|
||||
fileNames,
|
||||
function(fileName) { return {'file_name': fileName}; }
|
||||
)
|
||||
var request,
|
||||
self = this;
|
||||
expect(jasmine.Ajax.requests.count()).toEqual(caseInfo.numFiles);
|
||||
_.each(_.range(caseInfo.numFiles), function(index) {
|
||||
request = jasmine.Ajax.requests.at(index);
|
||||
expect(request.url).toEqual(self.postUrl);
|
||||
expect(request.method).toEqual('POST');
|
||||
expect(request.requestHeaders['Content-Type']).toEqual('application/json');
|
||||
expect(request.requestHeaders.Accept).toContain('application/json');
|
||||
expect(JSON.parse(request.params)).toEqual({
|
||||
files: [{file_name: fileNames[index]}]
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should trigger the global AJAX error handler on server error', function() {
|
||||
it('should trigger the notification error handler on server error', function() {
|
||||
this.request.respondWith({status: 500});
|
||||
expect(this.globalAjaxError).toHaveBeenCalled();
|
||||
expect(this.view.fileErrorMsg).toBeDefined();
|
||||
expect(this.view.fileErrorMsg.options.title).toEqual('Your file could not be uploaded');
|
||||
});
|
||||
|
||||
describe('and successful server response', function() {
|
||||
@@ -269,8 +305,8 @@ define(
|
||||
}
|
||||
});
|
||||
|
||||
it('should not trigger the global AJAX error handler', function() {
|
||||
expect(this.globalAjaxError).not.toHaveBeenCalled();
|
||||
it('should not trigger the notification error handler', function() {
|
||||
expect(this.view.fileErrorMsg).toBeNull();
|
||||
});
|
||||
|
||||
if (caseInfo.numFiles > concurrentUploadLimit) {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
define([
|
||||
'jquery',
|
||||
'underscore',
|
||||
'underscore.string',
|
||||
'backbone',
|
||||
'js/models/active_video_upload',
|
||||
'js/views/baseview',
|
||||
@@ -10,10 +11,12 @@ define([
|
||||
'text!templates/active-video-upload-list.underscore',
|
||||
'jquery.fileupload'
|
||||
],
|
||||
function($, _, Backbone, ActiveVideoUpload, BaseView, ActiveVideoUploadView, NotificationView, HtmlUtils,
|
||||
function($, _, str, Backbone, ActiveVideoUpload, BaseView, ActiveVideoUploadView, NotificationView, HtmlUtils,
|
||||
activeVideoUploadListTemplate) {
|
||||
'use strict';
|
||||
var ActiveVideoUploadListView = BaseView.extend({
|
||||
var ActiveVideoUploadListView,
|
||||
CONVERSION_FACTOR_GBS_TO_BYTES = 1000 * 1000 * 1000;
|
||||
ActiveVideoUploadListView = BaseView.extend({
|
||||
tagName: 'div',
|
||||
events: {
|
||||
'click .file-drop-area': 'chooseFile',
|
||||
@@ -29,6 +32,7 @@ define([
|
||||
this.concurrentUploadLimit = options.concurrentUploadLimit || 0;
|
||||
this.postUrl = options.postUrl;
|
||||
this.videoSupportedFileFormats = options.videoSupportedFileFormats;
|
||||
this.videoUploadMaxFileSizeInGB = options.videoUploadMaxFileSizeInGB;
|
||||
this.onFileUploadDone = options.onFileUploadDone;
|
||||
if (options.uploadButton) {
|
||||
options.uploadButton.click(this.chooseFile.bind(this));
|
||||
@@ -136,34 +140,48 @@ define([
|
||||
uploadData.cid = model.cid; // eslint-disable-line no-param-reassign
|
||||
uploadData.submit();
|
||||
} else {
|
||||
$.ajax({
|
||||
url: this.postUrl,
|
||||
contentType: 'application/json',
|
||||
data: JSON.stringify({
|
||||
files: _.map(
|
||||
uploadData.files,
|
||||
function(file) {
|
||||
return {file_name: file.name, content_type: file.type};
|
||||
_.each(
|
||||
uploadData.files,
|
||||
function(file) {
|
||||
$.ajax({
|
||||
url: view.postUrl,
|
||||
contentType: 'application/json',
|
||||
data: JSON.stringify({
|
||||
files: [{file_name: file.name, content_type: file.type}]
|
||||
}),
|
||||
dataType: 'json',
|
||||
type: 'POST',
|
||||
global: false // Do not trigger global AJAX error handler
|
||||
}).done(function(responseData) {
|
||||
_.each(
|
||||
responseData.files,
|
||||
function(file) { // eslint-disable-line no-shadow
|
||||
view.$uploadForm.fileupload('add', {
|
||||
files: _.filter(uploadData.files, function(fileObj) {
|
||||
return file.file_name === fileObj.name;
|
||||
}),
|
||||
url: file.upload_url,
|
||||
videoId: file.edx_video_id,
|
||||
multipart: false,
|
||||
global: false, // Do not trigger global AJAX error handler
|
||||
redirected: true
|
||||
});
|
||||
}
|
||||
);
|
||||
}).fail(function(response) {
|
||||
if (response.responseText) {
|
||||
try {
|
||||
errorMsg = JSON.parse(response.responseText).error;
|
||||
} catch (error) {
|
||||
errorMsg = str.truncate(response.responseText, 300);
|
||||
}
|
||||
} else {
|
||||
errorMsg = gettext('This may be happening because of an error with our server or your internet connection. Try refreshing the page or making sure you are online.'); // eslint-disable-line max-len
|
||||
}
|
||||
)
|
||||
}),
|
||||
dataType: 'json',
|
||||
type: 'POST'
|
||||
}).done(function(responseData) {
|
||||
_.each(
|
||||
responseData.files,
|
||||
function(file, index) {
|
||||
view.$uploadForm.fileupload('add', {
|
||||
files: [uploadData.files[index]],
|
||||
url: file.upload_url,
|
||||
videoId: file.edx_video_id,
|
||||
multipart: false,
|
||||
global: false, // Do not trigger global AJAX error handler
|
||||
redirected: true
|
||||
});
|
||||
}
|
||||
);
|
||||
});
|
||||
view.showErrorMessage(errorMsg);
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -198,6 +216,10 @@ define([
|
||||
this.setStatus(data.cid, ActiveVideoUpload.STATUS_FAILED);
|
||||
},
|
||||
|
||||
getMaxFileSizeInBytes: function() {
|
||||
return this.videoUploadMaxFileSizeInGB * CONVERSION_FACTOR_GBS_TO_BYTES;
|
||||
},
|
||||
|
||||
hideErrorMessage: function() {
|
||||
if (this.fileErrorMsg) {
|
||||
this.fileErrorMsg.hide();
|
||||
@@ -212,13 +234,16 @@ define([
|
||||
},
|
||||
|
||||
showErrorMessage: function(errorMsg) {
|
||||
var titleMsg = gettext('Your file could not be uploaded');
|
||||
this.fileErrorMsg = new NotificationView.Error({
|
||||
title: titleMsg,
|
||||
message: errorMsg
|
||||
});
|
||||
this.fileErrorMsg.show();
|
||||
this.readMessages([titleMsg, errorMsg]);
|
||||
var titleMsg;
|
||||
if (!this.fileErrorMsg) {
|
||||
titleMsg = gettext('Your file could not be uploaded');
|
||||
this.fileErrorMsg = new NotificationView.Error({
|
||||
title: titleMsg,
|
||||
message: errorMsg
|
||||
});
|
||||
this.fileErrorMsg.show();
|
||||
this.readMessages([titleMsg, errorMsg]);
|
||||
}
|
||||
},
|
||||
|
||||
validateFile: function(data) {
|
||||
@@ -240,6 +265,14 @@ define([
|
||||
.replace('{supportedFileFormats}', self.videoSupportedFileFormats.join(' and '));
|
||||
return false;
|
||||
}
|
||||
if (file.size > self.getMaxFileSizeInBytes()) {
|
||||
error = gettext(
|
||||
'{filename} exceeds maximum size of {maxFileSizeInGB} GB.'
|
||||
)
|
||||
.replace('{filename}', fileName)
|
||||
.replace('{maxFileSizeInGB}', self.videoUploadMaxFileSizeInGB);
|
||||
return false;
|
||||
}
|
||||
});
|
||||
return error;
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user