diff --git a/entity-browser-app/src/main/kotlin/jetbrains/xodus/browser/web/db/StoreService.kt b/entity-browser-app/src/main/kotlin/jetbrains/xodus/browser/web/db/StoreService.kt index 72f27a8..c7480b8 100644 --- a/entity-browser-app/src/main/kotlin/jetbrains/xodus/browser/web/db/StoreService.kt +++ b/entity-browser-app/src/main/kotlin/jetbrains/xodus/browser/web/db/StoreService.kt @@ -135,6 +135,17 @@ class StoreService { } } + @Throws(IOException::class) + fun getBlobString(id: String, blobName: String): String { + val tx = store.beginReadonlyTransaction() + try { + val entity = getEntity(id, tx) + return entity.getBlobString(blobName) ?: throw NotFoundException("there is no blob $blobName") + } finally { + tx.commit() + } + } + private fun Entity.applyValues(property: EntityProperty) { property.value = safeTrim(property.value) val value = property.string2value() diff --git a/entity-browser-app/src/main/kotlin/jetbrains/xodus/browser/web/resources/Entities.kt b/entity-browser-app/src/main/kotlin/jetbrains/xodus/browser/web/resources/Entities.kt index db95a80..096f12a 100644 --- a/entity-browser-app/src/main/kotlin/jetbrains/xodus/browser/web/resources/Entities.kt +++ b/entity-browser-app/src/main/kotlin/jetbrains/xodus/browser/web/resources/Entities.kt @@ -13,6 +13,11 @@ import jetbrains.xodus.browser.web.AppRoute import jetbrains.xodus.browser.web.ChangeSummary import jetbrains.xodus.browser.web.WebApplication import mu.KLogging +import java.io.BufferedWriter +import java.io.InputStreamReader +import java.io.OutputStreamWriter +import java.net.URI +import java.nio.charset.StandardCharsets class Entities(webApp: WebApplication) : AppRoute, ResourceSupport(webApp) { @@ -88,6 +93,19 @@ class Entities(webApp: WebApplication) : AppRoute, ResourceSupport(webApp) { } } } + get("/{entityId}/blobString/{blobName}") { + val entityId = call.entityId + val blobName = call.parameters["blobName"] ?: "" + logger.debug { "getting entity by entity id '$entityId'" } + val encodedBlobName = URI(null, null, blobName, null).toASCIIString().replace(",".toRegex(), "%2C") + call.response.headers.append("Content-Disposition", "attachment; filename=$encodedBlobName.txt") + call.respondOutputStream(ContentType.parse("text/plain;charset=utf-8")) { + val blobString = call.storeService.getBlobString(entityId, blobName) + val writer = BufferedWriter(OutputStreamWriter(this, StandardCharsets.UTF_8)) + writer.write(blobString) + writer.flush() + } + } get("/{entityId}/links/{linkName}") { val entityId = call.entityId val linkName = call.parameters["linkName"] ?: "" diff --git a/entity-browser-frontend/app/controller/data-view.js b/entity-browser-frontend/app/controller/data-view.js index 3e6d3be..4b563b3 100644 --- a/entity-browser-frontend/app/controller/data-view.js +++ b/entity-browser-frontend/app/controller/data-view.js @@ -70,6 +70,10 @@ angular.module('xodus').controller('DataViewController', [ dataViewCtrl.blobLink = function (entity, blob) { return navigation.api.blobLink(entity.id, blob.name); }; + + dataViewCtrl.blobStringLink = function (entity, blob) { + return navigation.api.blobStringLink(entity.id, blob.name); + }; }; function newPager(searchTerm) { diff --git a/entity-browser-frontend/app/controller/form-view/blobs.js b/entity-browser-frontend/app/controller/form-view/blobs.js index efa94f0..8a06e45 100644 --- a/entity-browser-frontend/app/controller/form-view/blobs.js +++ b/entity-browser-frontend/app/controller/form-view/blobs.js @@ -10,5 +10,9 @@ angular.module('xodus').controller('BlobsController', [ return navigation.api.blobLink($scope.state.current.id, blob.name); }; + $scope.downloadStringLink = function (blob) { + return navigation.api.blobStringLink($scope.state.current.id, blob.name); + }; + }] ); \ No newline at end of file diff --git a/entity-browser-frontend/app/service/navigation.js b/entity-browser-frontend/app/service/navigation.js index c7b523c..e6baccf 100644 --- a/entity-browser-frontend/app/service/navigation.js +++ b/entity-browser-frontend/app/service/navigation.js @@ -9,6 +9,10 @@ angular.module('xodus').factory('navigationService', [ return 'api/dbs/' + db.uuid + '/entities/' + entityId + "/blob/" + name; } + function blobStringLink(entityId, name) { + return 'api/dbs/' + db.uuid + '/entities/' + entityId + "/blobString/" + name; + } + function toType(typeId) { return angular.isDefined(typeId) ? $location.path(prefix).search({typeId: typeId.toString()}) : toType(0); } @@ -40,7 +44,8 @@ angular.module('xodus').factory('navigationService', [ toEntity: toEntity, forceReload: forceReload, api: { - blobLink: blobLink + blobLink: blobLink, + blobStringLink: blobStringLink } }; }; diff --git a/entity-browser-frontend/app/templates/data-view.html b/entity-browser-frontend/app/templates/data-view.html index 967e33e..4f3e75a 100644 --- a/entity-browser-frontend/app/templates/data-view.html +++ b/entity-browser-frontend/app/templates/data-view.html @@ -123,7 +123,11 @@

- + Binary + + + UTF