Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for chunked and resumable file uploads #5516

Merged
merged 63 commits into from
Mar 14, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
63 commits
Select commit Hold shift + click to select a range
c83c38c
Add basic structure to support chunked file uploads
guerler Feb 8, 2018
2eb4fa5
Fix debug statements
guerler Feb 11, 2018
6de3353
Remove debugging script, submit actual data
guerler Feb 12, 2018
96d3e80
Modify progress handler to accomodate chunks
guerler Feb 12, 2018
313f165
Use let instead of var for for-loops
guerler Feb 12, 2018
afe0b6a
Use regular debug statements instead of logger
guerler Feb 12, 2018
d9c9482
Reuse submission helper
guerler Feb 13, 2018
309dfbf
Remove redundant log
guerler Feb 13, 2018
8805d09
Add file data name parameter
guerler Feb 13, 2018
ca23825
Fix for collection handler
guerler Feb 13, 2018
ca2c300
Reduce chunk size for testing, remove debug output
guerler Feb 14, 2018
09bd908
Fix chunk sizes
guerler Feb 14, 2018
5e26c03
Fix comment
guerler Feb 14, 2018
975bd2f
Submit file segments in request body, use header parameters
guerler Feb 16, 2018
c5337fe
Parse file and chunk data to post helper
guerler Feb 17, 2018
488ce62
Use template literal, fix session id parsing
guerler Feb 17, 2018
0f69eaf
Rename header parameter
guerler Feb 17, 2018
b56bec0
Fix template string
guerler Feb 17, 2018
2b18782
Parse nginx upload directory to client
guerler Feb 17, 2018
3951262
Reuse existing request helper for whole file submission
guerler Feb 17, 2018
937fe61
Fix success response parsing
guerler Feb 17, 2018
bd9ce25
Fix comments
guerler Feb 17, 2018
ceedcb5
Consolidate helpers
guerler Feb 17, 2018
dee0cef
Merge branch 'dev' into chunk_uploads
guerler Feb 18, 2018
d95337b
Add tool submission request
guerler Feb 20, 2018
c04bb8c
Increase chunksize
guerler Feb 20, 2018
afd5c8d
Add warning notification
guerler Feb 20, 2018
ba859bf
Fix state handling, show warning message
guerler Feb 20, 2018
42e7ceb
Fix function declarations
guerler Feb 20, 2018
ecac866
Fix debug statement, increase chunk size to 50MB
guerler Feb 20, 2018
99d20ae
Resume uploads if server or nginx proxy reload
guerler Feb 20, 2018
4ac01cd
Remove/fix debug statements
guerler Feb 20, 2018
b50ca79
Add separate api endpoint to handle uploads
guerler Feb 20, 2018
093f332
Use api endpoint to store chunks
guerler Feb 21, 2018
11e0fde
Fix chunk size, close files properly
guerler Feb 21, 2018
f4ae4b7
Fix lint
guerler Feb 21, 2018
1a536ee
Remove unused nginx specifiers
guerler Feb 21, 2018
b0a4cb4
Properly handle error response
guerler Feb 21, 2018
ad5c8a3
Remove unused import
guerler Feb 23, 2018
c6b4d2e
Remove dependency from nginx variables, only pass session id
guerler Feb 23, 2018
789c41c
Raise proper value error if session id is invalid
guerler Feb 23, 2018
97f0530
Fix naming conflict between regular upload path and nginx path
guerler Feb 23, 2018
5047e92
Fix session condition, use literal templates
guerler Feb 23, 2018
9bd9112
Use literal template for tool panel
guerler Feb 23, 2018
19cffb5
Merge branch 'dev' into chunk_uploads
guerler Feb 23, 2018
6889232
Remove duplicate slash
guerler Feb 23, 2018
be50407
Escape workflow name
guerler Feb 26, 2018
2cae71a
Add upload chunk size setting to configuration
guerler Feb 26, 2018
cc64f58
Merge branch 'dev' into chunk_uploads
guerler Mar 8, 2018
ecc6ac5
Default to 100 in configuration manager
guerler Mar 8, 2018
d6a3964
Add additional checks, use join
guerler Mar 9, 2018
3f56aeb
Re-use regex to validate session id
guerler Mar 9, 2018
51a135b
Read chunks of chunks when writing target file
guerler Mar 9, 2018
529e98e
Rely on automated file closing, add new line
guerler Mar 10, 2018
a4287f1
Test chunked uploads
guerler Mar 12, 2018
a137420
Use ceil instead of floor
guerler Mar 13, 2018
2dba72f
Align chunk size check
guerler Mar 13, 2018
22dd4a8
Fix lint
guerler Mar 13, 2018
7589bbb
Specify chunk size in bytes instead of megabytes
guerler Mar 13, 2018
71c8809
Remove unused import
guerler Mar 13, 2018
8d1e0fc
Add chunk size config option to schema
guerler Mar 13, 2018
941017b
Moderate chunk size for upload tests
guerler Mar 13, 2018
7595114
Fix typo
guerler Mar 14, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
92 changes: 39 additions & 53 deletions client/galaxy/scripts/apps/panels/tool-panel.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import Tools from "mvc/tool/tools";
import Upload from "mvc/upload/upload-view";
import _l from "utils/localization";
import ToolForm from "mvc/tool/tool-form-composite";
import _ from "libs/underscore";

var ToolPanel = Backbone.View.extend({
initialize: function(page, options) {
Expand All @@ -28,7 +29,8 @@ var ToolPanel = Backbone.View.extend({

// add upload modal
this.upload_button = new Upload({
nginx_upload_path: config.nginx_upload_path,
upload_path: config.nginx_upload_path || `${Galaxy.root}api/tools`,
chunk_upload_size: config.chunk_upload_size,
ftp_upload_site: config.ftp_upload_site,
default_genome: config.default_genome,
default_extension: config.default_extension
Expand Down Expand Up @@ -74,70 +76,54 @@ var ToolPanel = Backbone.View.extend({

/** build a link to one tool */
_templateTool: function(tool) {
return [
'<div class="toolTitle">',
'<a href="',
this.root,
tool.href,
'" target="galaxy_main">',
tool.title,
"</a>",
"</div>"
].join("");
return `<div class="toolTitle">
<a href="${Galaxy.root}${tool.href}" target="galaxy_main">
${tool.title}
</a>
</div>`;
},

/** build a link to 'All Workflows' */
_templateAllWorkflow: function(tool) {
return [
'<div class="toolTitle">',
// global
'<a href="',
Galaxy.root,
tool.href,
'">',
tool.title,
"</a>",
"</div>"
].join("");
return `<div class="toolTitle">
<a href="${Galaxy.root}${tool.href}">
${tool.title}
</a>
</div>`;
},

/** build links to workflows in toolpanel */
_templateWorkflowLink: function(wf) {
return [
'<div class="toolTitle">',
`<a class="${wf.cls} " href="`,
Galaxy.root,
wf.href,
'">',
wf.title,
"</a>",
"</div>"
].join("");
return `<div class="toolTitle">
<a class="${wf.cls}" href="${Galaxy.root}${wf.href}">
${_.escape(wf.title)}
</a>
</div>`;
},

/** override to include inital menu dom and workflow section */
_template: function() {
return [
'<div class="toolMenuContainer">',
'<div class="toolMenu" style="display: none">',
'<div id="search-no-results" style="display: none; padding-top: 5px">',
"<em><strong>",
_l("Search did not match any tools."),
"</strong></em>",
"</div>",
"</div>",
'<div class="toolSectionPad"/>',
'<div class="toolSectionPad"/>',
'<div class="toolSectionTitle" id="title_XXinternalXXworkflow">',
"<span>",
_l("Workflows"),
"</span>",
"</div>",
'<div id="internal-workflows" class="toolSectionBody">',
'<div class="toolSectionBg"/>',
"</div>",
"</div>"
].join("");
return `<div class="toolMenuContainer">
<div class="toolMenu" style="display: none">
<div id="search-no-results" style="display: none; padding-top: 5px">
<em>
<strong>
${_l("Search did not match any tools.")}
</strong>
</em>
</div>
</div>
<div class="toolSectionPad"/>
<div class="toolSectionPad"/>
<div class="toolSectionTitle" id="title_XXinternalXXworkflow">
<span>
${_l("Workflows")}
</span>
</div>
<div id="internal-workflows" class="toolSectionBody">
<div class="toolSectionBg"/>
</div>
</div>`;
},

toString: function() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ export default Backbone.View.extend({

// file upload
this.uploadbox = this.$(".upload-box").uploadbox({
url: this.app.options.nginx_upload_path,
url: this.app.options.upload_path,
announce: function(index, file) {
self._eventAnnounce(index, file);
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ export default Backbone.View.extend({
});
});
$.uploadpost({
url: this.app.options.nginx_upload_path,
url: this.app.options.upload_path,
data: this.app.toData(this.collection.filter()),
success: function(message) {
self._eventSuccess(message);
Expand Down
11 changes: 8 additions & 3 deletions client/galaxy/scripts/mvc/upload/default/default-row.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export default Backbone.View.extend({
init: "upload-icon-button fa fa-trash-o",
queued: "upload-icon fa fa-spinner fa-spin",
running: "upload-icon fa fa-spinner fa-spin",
warning: "upload-icon fa fa-spinner fa-spin",
success: "upload-icon-button fa fa-check",
error: "upload-icon-button fa fa-exclamation-triangle"
},
Expand Down Expand Up @@ -183,7 +184,7 @@ export default Backbone.View.extend({
_refreshInfo: function() {
var info = this.model.get("info");
if (info) {
this.$info_text.html(`<strong>Failed: </strong>${info}`).show();
this.$info_text.html(`<strong>Warning: </strong>${info}`).show();
} else {
this.$info_text.hide();
}
Expand Down Expand Up @@ -213,13 +214,17 @@ export default Backbone.View.extend({
this.select_genome.disable();
this.select_extension.disable();
}
this.$info_progress.show();
this.$el.removeClass().addClass("upload-row");
if (status == "success") {
this.$el.addClass("success");
this.$percentage.html("100%");
}
if (status == "error") {
} else if (status == "error") {
this.$el.addClass("danger");
this.$info_progress.hide();
} else if (status == "warning") {
this.$el.addClass("warning");
this.$info_progress.hide();
}
},

Expand Down
84 changes: 48 additions & 36 deletions client/galaxy/scripts/mvc/upload/default/default-view.js
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ export default Backbone.View.extend({

// file upload
this.uploadbox = this.$uploadbox.uploadbox({
url: this.app.options.nginx_upload_path,
url: this.app.options.upload_path,
announce: function(index, file) {
self._eventAnnounce(index, file);
},
Expand All @@ -120,6 +120,9 @@ export default Backbone.View.extend({
error: function(index, message) {
self._eventError(index, message);
},
warning: function(index, message) {
self._eventWarning(index, message);
},
complete: function() {
self._eventComplete();
},
Expand Down Expand Up @@ -247,7 +250,7 @@ export default Backbone.View.extend({
/** Progress */
_eventProgress: function(index, percentage) {
var it = this.collection.get(index);
it.set("percentage", percentage);
it.set({percentage: percentage, status: "running", info: ""});
this.ui_button.model.set("percentage", this._uploadPercentage(percentage, it.get("file_size")));
},

Expand All @@ -263,6 +266,12 @@ export default Backbone.View.extend({
Galaxy.currHistoryPanel.refreshContents();
},

/** Warning */
_eventWarning: function(index, message) {
var it = this.collection.get(index);
it.set({ status: "warning", info: message });
},

/** Error */
_eventError: function(index, message) {
var it = this.collection.get(index);
Expand Down Expand Up @@ -363,7 +372,10 @@ export default Backbone.View.extend({
this._uploadFtp();

// queue remaining files
this.uploadbox.start();
this.uploadbox.start({
id: Galaxy.user.id,
chunk_upload_size: this.app.options.chunk_upload_size
});
this.render();
}
},
Expand Down Expand Up @@ -430,7 +442,7 @@ export default Backbone.View.extend({
if (list.length > 0) {
$.uploadpost({
data: this.app.toData(list),
url: this.app.options.nginx_upload_path,
url: this.app.options.upload_path,
success: function(message) {
_.each(list, model => {
self._eventSuccess(model.id);
Expand All @@ -452,37 +464,37 @@ export default Backbone.View.extend({

/** Template */
_template: function() {
return (
'<div class="upload-view-default">' +
'<div class="upload-top">' +
'<h6 class="upload-top-info"/>' +
"</div>" +
'<div class="upload-box">' +
'<div class="upload-helper"><i class="fa fa-files-o"/>Drop files here</div>' +
'<table class="upload-table ui-table-striped" style="display: none;">' +
"<thead>" +
"<tr>" +
"<th>Name</th>" +
"<th>Size</th>" +
"<th>Type</th>" +
"<th>Genome</th>" +
"<th>Settings</th>" +
"<th>Status</th>" +
"<th/>" +
"</tr>" +
"</thead>" +
"<tbody/>" +
"</table>" +
"</div>" +
'<div class="upload-footer">' +
'<span class="upload-footer-title">Type (set all):</span>' +
'<span class="upload-footer-extension"/>' +
'<span class="upload-footer-extension-info upload-icon-button fa fa-search"/> ' +
'<span class="upload-footer-title">Genome (set all):</span>' +
'<span class="upload-footer-genome"/>' +
"</div>" +
'<div class="upload-buttons"/>' +
"</div>"
);
return `<div class="upload-view-default">
<div class="upload-top">
<h6 class="upload-top-info"/>
</div>
<div class="upload-box">
<div class="upload-helper">
<i class="fa fa-files-o"/>Drop files here
</div>
<table class="upload-table ui-table-striped" style="display: none;">
<thead>
<tr>
<th>Name</th>
<th>Size</th>
<th>Type</th>
<th>Genome</th>
<th>Settings</th>
<th>Status</th>
<th/>
</tr>
</thead>
<tbody/>
</table>
</div>
<div class="upload-footer">
<span class="upload-footer-title">Type (set all):</span>
<span class="upload-footer-extension"/>
<span class="upload-footer-extension-info upload-icon-button fa fa-search"/>
<span class="upload-footer-title">Genome (set all):</span>
<span class="upload-footer-genome"/>
</div>
<div class="upload-buttons"/>
</div>`;
}
});
1 change: 0 additions & 1 deletion client/galaxy/scripts/mvc/upload/upload-view.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import UploadViewComposite from "mvc/upload/composite/composite-view";
import UploadViewCollection from "mvc/upload/collection/collection-view";
export default Backbone.View.extend({
options: {
nginx_upload_path: "",
ftp_upload_site: "n/a",
default_genome: "?",
default_extension: "auto",
Expand Down
Loading