BLOB stores (attributes of type Document
on ORM level)
Entity attribute of Document
type with storeName
property for
this attribute should be defined. Content (data stored in the database) of
such attributes is a meta-information about file - a serialized
BlobStoreItem object, not an actual file content.
In case entity is stored in the database using mStorage mixin, DDL generator create nvarchar(2000) field in database and store there BlobStoreItem serialized to JSON.
For Virtual entity developer should implement select
method and fill BlobStoreItem manually
(for example by parsing file content as done in ubm_form).
In the store definition section of application config developer describe stores. Each store must implement interface described below.
The store class itself provide storing and retrieving file content (based on meta-information stored in the entity attribute).
From client-side POV uploading files to server is separated onto two part. Like in gmail when you send mail with attachment you can attach a file, and gmail send it to server, but you do not send mail itself yet - this is first stage. Result of this stage is information about where file is stored on the server side. When you send email client pass to server email attributes, body and information about attached files. This is the same UnityBase do in the second stage.
Server side usage:
// get dirty (not committed yet) content of my_entity.docAttribute with ID = 12312 as ArrayBuffer
let tmpContent = App.blobStores.getContent(
{ID: 12312, entity: 'my_entity', attribute: 'blobAttribute', isDirty: true},
{encoding: 'bin'}
)
// get BLOB content of my_entity.docAttribute with ID = 12312 as base64 string
let base64Content = App.blobStores.getContent(
{ID: 12312, entity: 'my_entity', attribute: 'blobAttribute'},
{encoding: 'base64'}
)
// get BLOB content of my_entity.docAttribute with ID = 12312 as string
let base64Content = App.blobStores.getContent(
{ID: 12312, entity: 'my_entity', attribute: 'blobAttribute'},
{encoding: 'utf8'}
)
// put a file into BLOB store
let blobItem = App.blobStores.putContent(
{ID: 12312, entity: 'my_entity', attribute: 'blobAttribute'},
'/tpm/someHugeFile.zip',
{ contentIsFilePath: true }
)
// or read file and put it to BLOB store (not committed yet)
let content = fs.readFileSync(__filename, {encoding: 'bin'})
let fn = path.basename(__filename)
let blobItem = App.blobStores.putContent(
{ID: 12312, entity: 'my_entity', attribute: 'blobAttribute'},
content
)
// commit blob store
let dataStore = UB.DataStore(my_entity)
dataStore.run('update', {
execParams: {
ID: 12312,
blobAttribute: JSON.stringify(blobItem)
}
})
Upload file to server
In UnityBase upload file to server is performed in two stages:
-
Upload file to temporary store - on this stage client call setDocument app level method and pass file content to server with an additional parameter isDirty=true, server store file in the temporary place.
-
Client execute
insert
orupdate
entity method and pass (with other attributes) string, returned on the first stage as a value ofDocument
type attribute. On this stage server see what user want to update/insert Document and, based on Domain information, know what type of store is used for this attribute. Server: -
Finally, UnityBase update entity and commit database transaction (in case entity is non-virtual)
To enable support for client side large file uploading, set chunk size in mb
in ubConfig.json
, parameter uiSettings.uploadChunkSizeMb
.
Also, it's possible to pass different chunkSize
to setDocument's params, or pass null
or 0
to disable
UB.connection.setDocument(file, {
entity: 'my_entity',
attribute: 'blobAttribute',
origName: 'img.jpg',
filename: 'img.jpg',
chunkSize: 10
})
Download file from server
For download file from server client call getDocument
endpoint
Methods
# getContent (request: BlobStoreRequest, optionsopt: object) → string | UBMail.TubSendMailAttachKind.Buffer | ArrayBuffer | null inner
Retrieve BLOB content from the blob store
Return null
in case attribute value is null.
# getContentPath (request: BlobStoreRequest) → string | null inner
Retrieve full path to a file with BLOB content Returns:
null
in case attribute value is null (document not assigned)- '' (empty string) in case store is not file based (reserved for future use)
- full path to file on success
- throws if parameters is invalid or document is not accessible
Arguments:
request
: BlobStoreRequest
# getContentPathAndBlobInfo (request: BlobStoreRequest) → Object | null inner
Retrieve full path to a file with BLOB content Returns:
null
in case attribute value is null (document not assigned)- '' (empty string) in case store is not file based (reserved for future use)
- full path to file on success
- throws if parameters is invalid or document is not accessible
Arguments:
request
: BlobStoreRequest
# getDocumentEndpointInternal (req: THTTPRequest, resp: THTTPResponse, withBody: boolean) → boolean inner
Internal endpoint function which accepts additional boolean flag after req, resp arguments. Checks access to the document, obtains it content from blobStore and, by default, sends it to response.
Arguments:
req
: THTTPRequestresp
: THTTPResponsewithBody
= true: booleanSet to
false
to check whether the document is available without sending it's body
# internalWriteDocumentToResp (requestParams: BlobStoreRequest, req: THTTPRequest, resp: THTTPResponse, skipRlsopt: boolean) → Object inner
Writes a BLOB content to the response without verifying an ALS (but RLS is verified) or return an error without modifying a response.
SECURITY - method can be used inside endpoint or rest entity method, which already checks the access rights to the document
Returns:
{success: false, reason: 'fail reason description}
if attribute value is empty or record with specified ID not found or not accessible or entity/attribute is unknown or id not passed etc.{success: true}
if content is written to the response
Arguments:
requestParams
: BlobStoreRequestreq
: THTTPRequestresp
: THTTPResponseskipRls
: booleanDo not check RLS, when query blobInfo. NOTE! The caller of this method is responsible for appropriate security check then!
# markRevisionAsPermanent (request: BlobStoreRequest) inner
For a historical BLOB stores mark specified revision as a permanent. Permanents revisions will not be deleted during history rotation.
Arguments:
request
: BlobStoreRequestrevision
: numberrevision to be marked as permanent
const UB = require(@unitybase/ub')
UB.App.blobStores.markRevisionAsPermanent({
entity: 'my_entity',
attribute: 'attributeOfTypeDocument',
ID: 1000,
revision: 2
})
# putContent (request: BlobStoreRequest, content: ArrayBuffer | UBMail.TubSendMailAttachKind.Buffer | string | THTTPRequest, optionsopt: object) → BlobStoreItem inner
Server-side method for putting BLOB content to BLOB store temporary storage. Can accept a THTTPRequest as a content, in this case request body will be used as BLOB content
Arguments:
request
: BlobStoreRequestcontent
: ArrayBuffer| UBMail.TubSendMailAttachKind.Buffer| string| THTTPRequestoptions
: objectcontentIsFilePath
: booleancontent is a path to file
// convert base64 encoded string stored in `prm.signature` to binary and put to the store
docContent = App.blobStores.putContent({
entity: 'iit_signature',
attribute: 'signature',
ID: ID,
fileName: ID + '.p7s'
}, Buffer.from(prm.signature, 'base64'))
# shred (entityCode: string, attributeName: string, IDs: number) inner
Server-side method for completely remove, including all historical revisions all BLOBs content for specified entity, attribute and ID(s).
In case content storage (filesystem/s3 bucket) is readonly - such content not removed
WARNING irreversible operation
# shredAll (entityCode: string, IDs: number) inner
Server-side method for completely remove, including all historical revisions all BLOBs contents for specified entity and ID(s).
In case content storage (filesystem/s3 bucket) is readonly - such content not removed
WARNING irreversible operation
# writeDocumentToResp (requestParams: BlobStoreRequest, req: THTTPRequest, resp: THTTPResponse, withBody: boolean) → boolean inner
Obtains the document content from a blobStore and sends it to the response
Arguments:
requestParams
: BlobStoreRequestreq
: THTTPRequestresp
: THTTPResponsewithBody
= true: booleanSet to
false
to check if the document is available without sending its body
Types
# BlobStoreItem inner
Blob store item content (JSON stored in database)
Properties
v
opt : numberStore version. Empty for UB<5. Store implementation must check
v
for backward compatibilitystore
: stringCode of store implementation from application config. If empty - use a store from attribute configuration
fName
: stringFile name inside store (auto generated in most case)
origName
: stringOriginal file name (as user upload it)
relPath
opt : stringRelative path of fName inside store folder (for file-based stores)
ct
: stringContent type
size
: numberContent size
md5
: stringContent MD5 checksum
revision
opt : numberContent revision. Used only for stores with
historyDepth
> 0deleting
opt : booleanIf true content must be deleted/archived during commit
isDirty
opt : boolean????
isPermanent
opt : booleanIf
true
- do not delete content during history rotation
# BlobStoreRequest inner
Blob store request (parameters passed to get|setDocument)
Properties