You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@airavata.apache.org by ma...@apache.org on 2019/12/05 19:30:48 UTC
[airavata-django-portal] branch master updated: AIRAVATA-3281 Use
mime-type when loading output files
This is an automated email from the ASF dual-hosted git repository.
machristie pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/airavata-django-portal.git
The following commit(s) were added to refs/heads/master by this push:
new b6770e0 AIRAVATA-3281 Use mime-type when loading output files
b6770e0 is described below
commit b6770e0a13a35134d2c2aa61c5ea57872b3accea
Author: Marcus Christie <ma...@apache.org>
AuthorDate: Thu Dec 5 14:30:29 2019 -0500
AIRAVATA-3281 Use mime-type when loading output files
---
.../js/models/ApplicationInterfaceDefinition.js | 14 +++++-
.../js/models/OutputDataObjectType.js | 55 +++++++++++++---------
django_airavata/apps/api/views.py | 15 ++++--
.../output-displays/DefaultOutputDisplay.vue | 17 ++++++-
.../common/js/components/DataProductViewer.vue | 16 ++++++-
5 files changed, 84 insertions(+), 33 deletions(-)
diff --git a/django_airavata/apps/api/static/django_airavata_api/js/models/ApplicationInterfaceDefinition.js b/django_airavata/apps/api/static/django_airavata_api/js/models/ApplicationInterfaceDefinition.js
index 8aa28e2..d71e6f0 100644
--- a/django_airavata/apps/api/static/django_airavata_api/js/models/ApplicationInterfaceDefinition.js
+++ b/django_airavata/apps/api/static/django_airavata_api/js/models/ApplicationInterfaceDefinition.js
@@ -49,12 +49,22 @@ export default class ApplicationInterfaceDefinition extends BaseModel {
const stdout = new OutputDataObjectType({
name: "Standard-Out",
type: DataType.STDOUT,
- isRequired: true
+ isRequired: true,
+ metaData: {
+ "file-metadata": {
+ "mime-type": "text/plain"
+ }
+ }
});
const stderr = new OutputDataObjectType({
name: "Standard-Error",
type: DataType.STDERR,
- isRequired: true
+ isRequired: true,
+ metaData: {
+ "file-metadata": {
+ "mime-type": "text/plain"
+ }
+ }
});
if (!this.applicationOutputs) {
this.applicationOutputs = [];
diff --git a/django_airavata/apps/api/static/django_airavata_api/js/models/OutputDataObjectType.js b/django_airavata/apps/api/static/django_airavata_api/js/models/OutputDataObjectType.js
index 5aaad3b..81bfa50 100644
--- a/django_airavata/apps/api/static/django_airavata_api/js/models/OutputDataObjectType.js
+++ b/django_airavata/apps/api/static/django_airavata_api/js/models/OutputDataObjectType.js
@@ -1,41 +1,40 @@
-
-import BaseModel from './BaseModel';
-import DataType from './DataType';
-import uuidv4 from 'uuid/v4';
+import BaseModel from "./BaseModel";
+import DataType from "./DataType";
+import uuidv4 from "uuid/v4";
const FIELDS = [
- 'name',
- 'value',
+ "name",
+ "value",
{
- name: 'type',
+ name: "type",
type: DataType,
- default: DataType.URI,
+ default: DataType.URI
},
- 'applicationArgument',
+ "applicationArgument",
{
- name: 'isRequired',
- type: 'boolean',
+ name: "isRequired",
+ type: "boolean",
default: false
},
{
- name: 'requiredToAddedToCommandLine',
- type: 'boolean',
- default: false,
+ name: "requiredToAddedToCommandLine",
+ type: "boolean",
+ default: false
},
{
- name: 'dataMovement',
- type: 'boolean',
+ name: "dataMovement",
+ type: "boolean",
default: false
},
- 'location',
- 'searchQuery',
+ "location",
+ "searchQuery",
{
- name: 'outputStreaming',
- type: 'boolean',
+ name: "outputStreaming",
+ type: "boolean",
default: false
},
- 'storageResourceId',
- 'metaData'
+ "storageResourceId",
+ "metaData"
];
export default class OutputDataObjectType extends BaseModel {
@@ -48,6 +47,16 @@ export default class OutputDataObjectType extends BaseModel {
get key() {
return this._key;
}
+
+ get fileMetadata() {
+ return this.metaData ? this.metaData["file-metadata"] : null;
+ }
+
+ get fileMetadataMimeType() {
+ return this.fileMetadata && this.fileMetadata["mime-type"]
+ ? this.fileMetadata["mime-type"]
+ : null;
+ }
}
-OutputDataObjectType.VALID_DATA_TYPES = DataType.values
+OutputDataObjectType.VALID_DATA_TYPES = DataType.values;
diff --git a/django_airavata/apps/api/views.py b/django_airavata/apps/api/views.py
index 14ff2c3..c5d22cb 100644
--- a/django_airavata/apps/api/views.py
+++ b/django_airavata/apps/api/views.py
@@ -944,21 +944,28 @@ def tus_upload_finish(request):
def download_file(request):
# TODO check that user has access to this file using sharing API
data_product_uri = request.GET.get('data-product-uri', '')
+ force_download = 'download' in request.GET
data_product = None
try:
data_product = request.airavata_client.getDataProduct(
request.authz_token, data_product_uri)
+ mime_type = "application/octet-stream" # default mime-type
+ if (data_product.productMetadata and
+ 'mime-type' in data_product.productMetadata):
+ mime_type = data_product.productMetadata['mime-type']
+ # 'mime-type' url parameter overrides
+ mime_type = request.GET.get('mime-type', mime_type)
except Exception as e:
log.warning("Failed to load DataProduct for {}"
.format(data_product_uri), exc_info=True)
raise Http404("data product does not exist") from e
try:
data_file = data_products_helper.open(request, data_product)
- response = FileResponse(data_file,
- content_type="application/octet-stream")
+ response = FileResponse(data_file, content_type=mime_type)
file_name = os.path.basename(data_file.name)
- response['Content-Disposition'] = ('attachment; filename="{}"'
- .format(file_name))
+ if mime_type == 'application/octet-stream' or force_download:
+ response['Content-Disposition'] = ('attachment; filename="{}"'
+ .format(file_name))
return response
except ObjectDoesNotExist as e:
raise Http404(str(e)) from e
diff --git a/django_airavata/apps/workspace/static/django_airavata_workspace/js/components/experiment/output-displays/DefaultOutputDisplay.vue b/django_airavata/apps/workspace/static/django_airavata_workspace/js/components/experiment/output-displays/DefaultOutputDisplay.vue
index 088ff62..25c1804 100644
--- a/django_airavata/apps/workspace/static/django_airavata_workspace/js/components/experiment/output-displays/DefaultOutputDisplay.vue
+++ b/django_airavata/apps/workspace/static/django_airavata_workspace/js/components/experiment/output-displays/DefaultOutputDisplay.vue
@@ -4,6 +4,7 @@
v-for="dp in dataProducts"
:data-product="dp"
:key="dp.productUri"
+ :mime-type="fileMimeType"
/>
</div>
</template>
@@ -29,8 +30,20 @@ export default {
},
components: {
"data-product-viewer": components.DataProductViewer
+ },
+ computed: {
+ fileMimeType() {
+ if (this.experimentOutput.fileMetadataMimeType) {
+ return this.experimentOutput.fileMetadataMimeType;
+ } else if (
+ this.experimentOutput.dataType === models.DataType.STDOUT ||
+ this.experimentOutput.dataType === models.DataType.STDERR
+ ) {
+ return "text/plain";
+ } else {
+ return null;
+ }
+ }
}
};
</script>
-
-
diff --git a/django_airavata/static/common/js/components/DataProductViewer.vue b/django_airavata/static/common/js/components/DataProductViewer.vue
index cb9fd86..52f35f7 100644
--- a/django_airavata/static/common/js/components/DataProductViewer.vue
+++ b/django_airavata/static/common/js/components/DataProductViewer.vue
@@ -1,7 +1,7 @@
<template>
- <span v-if="dataProduct.downloadURL">
- <a :href="dataProduct.downloadURL" class="action-link">
+ <span v-if="downloadURL">
+ <a :href="downloadURL" class="action-link">
<i class="fa fa-download"></i>
{{ filename }}
</a>
@@ -21,6 +21,9 @@ export default {
inputFile: {
type: Boolean,
default: false
+ },
+ mimeType: {
+ type: String
}
},
computed: {
@@ -33,6 +36,15 @@ export default {
} else {
return this.dataProduct.filename;
}
+ },
+ downloadURL() {
+ if (!this.dataProduct.downloadURL) {
+ return null;
+ } else if (this.mimeType) {
+ return `${this.dataProduct.downloadURL}&mime-type=${encodeURIComponent(this.mimeType)}`;
+ } else {
+ return this.dataProduct.downloadURL;
+ }
}
}
};