diff --git a/grails-app/assets/javascripts/bulk-import-view-models.js b/grails-app/assets/javascripts/bulk-import-view-models.js index e3a5c7443..4a8e1267c 100644 --- a/grails-app/assets/javascripts/bulk-import-view-models.js +++ b/grails-app/assets/javascripts/bulk-import-view-models.js @@ -382,6 +382,10 @@ function BulkUploadViewModel(activityImport) { dataType: "json", success: function (response) { activityImport.dataToLoad(response.data); + }, + error: function (jqXHR, status, error) { + var resp = jqXHR.responseJSON && jqXHR.responseJSON.error || ""; + message('Failed to convert file to data
' + resp); } }); return convertExcelToJSONRequest; diff --git a/grails-app/controllers/au/org/ala/biocollect/BioActivityController.groovy b/grails-app/controllers/au/org/ala/biocollect/BioActivityController.groovy index bd8f563c5..7f56c6162 100644 --- a/grails-app/controllers/au/org/ala/biocollect/BioActivityController.groovy +++ b/grails-app/controllers/au/org/ala/biocollect/BioActivityController.groovy @@ -31,6 +31,7 @@ import org.springframework.web.multipart.MultipartFile import static org.apache.http.HttpStatus.SC_BAD_REQUEST import static org.apache.http.HttpStatus.SC_OK +import static org.apache.http.HttpStatus.SC_INTERNAL_SERVER_ERROR @SecurityScheme(name = "auth", type = SecuritySchemeType.HTTP, @@ -1306,10 +1307,14 @@ class BioActivityController { if (pActivityId && type && file) { def content = activityService.convertExcelToOutputData(pActivityId, type, file) - render text: content as JSON + def status = SC_OK + if (content.error) { + status = SC_INTERNAL_SERVER_ERROR + } + render text: content as JSON, status: status } else { - render text: [message: "Missing required parameters - pActivityId, type & data (excel file)"] as JSON, status: HttpStatus.SC_BAD_REQUEST + render text: [message: "Missing required parameters - pActivityId, type & data (excel file)"] as JSON, status: SC_BAD_REQUEST } } diff --git a/grails-app/services/au/org/ala/biocollect/merit/ActivityService.groovy b/grails-app/services/au/org/ala/biocollect/merit/ActivityService.groovy index ac29e5b1f..346698c35 100644 --- a/grails-app/services/au/org/ala/biocollect/merit/ActivityService.groovy +++ b/grails-app/services/au/org/ala/biocollect/merit/ActivityService.groovy @@ -438,7 +438,12 @@ class ActivityService { } def convertExcelToOutputData(String id, String type, def file){ - def result = webService.postMultipart(grailsApplication.config.ecodata.service.url + "/metadata/extractOutputDataFromActivityExcelTemplate", [pActivityId: id, type: type], file, 'data') - result.content?.subMap('data') ?: result + def result = webService.postMultipart(grailsApplication.config.ecodata.service.url + "/metadata/extractOutputDataFromActivityExcelTemplate", [pActivityId: id, type: type], file, 'data', false, true) + if (result.error) { + return result.details + } + else { + return result.content?.subMap('data') ?: result + } } } diff --git a/grails-app/services/au/org/ala/biocollect/merit/WebService.groovy b/grails-app/services/au/org/ala/biocollect/merit/WebService.groovy index 1a7aba804..0f92970f1 100644 --- a/grails-app/services/au/org/ala/biocollect/merit/WebService.groovy +++ b/grails-app/services/au/org/ala/biocollect/merit/WebService.groovy @@ -443,11 +443,12 @@ class WebService { * @param url the URL to forward to. * @param params the (string typed) HTTP parameters to be attached. * @param file the Multipart file object to forward. + * @param includeFailureDetails if true, the return value will include response body. If content type is JSON, an object will be returned in `details` property. * @return [status:, content: */ - def postMultipart(url, Map params, MultipartFile file, fileParam = 'files', boolean useToken = false) { + def postMultipart(url, Map params, MultipartFile file, fileParam = 'files', boolean useToken = false, boolean includeFailureDetails = false) { - postMultipart(url, params, file.inputStream, file.contentType, file.originalFilename, fileParam, useToken) + postMultipart(url, params, file.inputStream, file.contentType, file.originalFilename, fileParam, useToken, includeFailureDetails) } /** @@ -460,7 +461,7 @@ class WebService { * @param fileParamName the name of the HTTP parameter that will be used for the post. * @return [status:, content: */ - def postMultipart(url, Map params, InputStream contentIn, contentType, originalFilename, fileParamName = 'files', boolean useToken = false) { + def postMultipart(url, Map params, InputStream contentIn, contentType, originalFilename, fileParamName = 'files', boolean useToken = false, boolean includeFailureDetails = false) { def result = [:] def user = userService.getUser() @@ -496,9 +497,11 @@ class WebService { result.content = message } - response.failure = {resp -> + response.failure = {resp, reader -> result.status = resp.status result.error = "Error POSTing to ${url}" + if (includeFailureDetails) + result.details = reader } } result