Merge pull request #14140 from edx/mushtaq/video-upload-restrict

Video upload restrictions
This commit is contained in:
Mushtaq Ali
2016-12-22 14:35:17 +05:00
committed by GitHub
6 changed files with 161 additions and 56 deletions

View File

@@ -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,

View File

@@ -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) {

View File

@@ -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;
},