diff --git a/crc/api.yml b/crc/api.yml
index 980d6d13..81d45f3a 100644
--- a/crc/api.yml
+++ b/crc/api.yml
@@ -705,6 +705,41 @@ paths:
type: string
format: binary
example: ''
+ /file/{file_id}/download :
+ parameters :
+ - name : file_id
+ in : path
+ required : true
+ description : The id of the File requested
+ schema :
+ type : integer
+ - name : auth_token
+ in : query
+ required : true
+ description : User Auth Toeken
+ schema :
+ type : string
+ - name : version
+ in : query
+ required : false
+ description : The version of the file, or none for latest version
+ schema :
+ type : integer
+ get :
+ operationId : crc.api.file.get_file_data_link
+ summary : Returns only the file contents
+ security: []
+ tags :
+ - Files
+ responses :
+ '200' :
+ description : Returns the actual file
+ content :
+ application/octet-stream :
+ schema :
+ type : string
+ format : binary
+ example : ''
/file/{file_id}/data:
parameters:
- name: file_id
diff --git a/crc/api/file.py b/crc/api/file.py
index 743d6327..619fd7ec 100644
--- a/crc/api/file.py
+++ b/crc/api/file.py
@@ -6,6 +6,7 @@ from flask import send_file
from crc import session
from crc.api.common import ApiError
+from crc.api.user import verify_token
from crc.models.api_models import DocumentDirectory, DocumentDirectorySchema
from crc.models.file import FileSchema, FileModel, File, FileModelSchema, FileDataModel, FileType
from crc.models.workflow import WorkflowSpecModel
@@ -179,6 +180,22 @@ def get_file_data(file_id, version=None):
)
+def get_file_data_link(file_id, auth_token, version=None):
+ if not verify_token(auth_token):
+ raise ApiError('not_authenticated', 'You need to include an authorization token in the URL with this')
+ file_data = FileService.get_file_data(file_id, version)
+ if file_data is None:
+ raise ApiError('no_such_file', 'The file id you provided does not exist')
+ return send_file(
+ io.BytesIO(file_data.data),
+ attachment_filename=file_data.file_model.name,
+ mimetype=file_data.file_model.content_type,
+ cache_timeout=-1, # Don't cache these files on the browser.
+ last_modified=file_data.date_created,
+ as_attachment = True
+ )
+
+
def get_file_info(file_id):
file_model = session.query(FileModel).filter_by(id=file_id).with_for_update().first()
if file_model is None:
diff --git a/crc/services/study_service.py b/crc/services/study_service.py
index 7774d2cc..4aa7a0a5 100644
--- a/crc/services/study_service.py
+++ b/crc/services/study_service.py
@@ -1,7 +1,9 @@
+import urllib
from copy import copy
from datetime import datetime
from typing import List
+import flask
import requests
from SpiffWorkflow import WorkflowException
from SpiffWorkflow.exceptions import WorkflowTaskExecException
@@ -288,9 +290,19 @@ class StudyService(object):
doc_files = FileService.get_files_for_study(study_id=study_id, irb_doc_code=code)
doc['count'] = len(doc_files)
doc['files'] = []
+
+ # when we run tests - it doesn't look like the user is available
+ # so we return a bogus token
+ token = 'not_available'
+ if hasattr(flask.g,'user'):
+ token = flask.g.user.encode_auth_token()
for file in doc_files:
doc['files'].append({'file_id': file.id,
'name': file.name,
+ 'url': app.config['APPLICATION_ROOT']+
+ 'file/' + str(file.id) +
+ '/download?auth_token='+
+ urllib.parse.quote_plus(token),
'workflow_id': file.workflow_id})
# update the document status to match the status of the workflow it is in.
diff --git a/tests/data/file_data_store/file_data_store.bpmn b/tests/data/file_data_store/file_data_store.bpmn
index 9af77bb0..ddc9e987 100644
--- a/tests/data/file_data_store/file_data_store.bpmn
+++ b/tests/data/file_data_store/file_data_store.bpmn
@@ -18,6 +18,10 @@
fileid = documents['UVACompl_PRCAppr'].files[0]['file_id']
+fileurl = documents['UVACompl_PRCAppr'].files[0]['url']
+
+filename = documents['UVACompl_PRCAppr'].files[0]['name']
+
file_data_set(file_id=fileid,key='test',value='me')
diff --git a/tests/test_file_datastore.py b/tests/test_file_datastore.py
index 2b95519e..1a10eea7 100644
--- a/tests/test_file_datastore.py
+++ b/tests/test_file_datastore.py
@@ -27,6 +27,8 @@ class TestFileDatastore(BaseTest):
processor = WorkflowProcessor(workflow)
processor.do_engine_steps()
task_data = processor.bpmn_workflow.last_task.data
+ self.assertTrue(str(task_data['fileid']) in task_data['fileurl'])
+ self.assertEqual(task_data['filename'],'anything.png')
self.assertEqual(task_data['output'], 'me')
self.assertEqual(task_data['output2'], 'nope')