mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-18 10:31:15 +00:00
✨ Introduce binary data management (#2059)
* introduce binary data management * merge fixes * fixes * init binary data manager for other modes * improve binary manager * improve binary manager * delete binary data on executions delete * lazy delete non-saved executions binary data * merge fixes + error handing * improve structure * leftovers and cleanups * formatting * fix config description * fixes * fix races * duplicate binary data for execute workflow node * clean up and cr * update mode name, add binary mode to diagnostics * update mode name, add prefix to filename * update filename * allow multiple modes, backward compatibility * improve file and id naming * use execution id for binary data storage * delete binary data by execution id * add meta for persisted binary data * delete marked persisted files * mark deletion by executionid * add env var for persisted binary data ttl * improvements * lint fix * fix env var description * cleanup * cleanup * ⚡ Minor improvements Co-authored-by: Jan Oberhauser <jan.oberhauser@gmail.com>
This commit is contained in:
@@ -179,6 +179,7 @@ export interface IRestApi {
|
||||
deleteExecutions(sendData: IExecutionDeleteFilter): Promise<void>;
|
||||
retryExecution(id: string, loadWorkflow?: boolean): Promise<boolean>;
|
||||
getTimezones(): Promise<IDataObject>;
|
||||
getBinaryBufferString(dataPath: string): Promise<string>;
|
||||
}
|
||||
|
||||
export interface INodeTranslationHeaders {
|
||||
|
||||
@@ -13,11 +13,7 @@
|
||||
<div v-if="!binaryData">
|
||||
{{ $locale.baseText('binaryDataDisplay.noDataFoundToDisplay') }}
|
||||
</div>
|
||||
<video v-else-if="binaryData.mimeType && binaryData.mimeType.startsWith('video/')" controls autoplay>
|
||||
<source :src="'data:' + binaryData.mimeType + ';base64,' + binaryData.data" :type="binaryData.mimeType">
|
||||
{{ $locale.baseText('binaryDataDisplay.yourBrowserDoesNotSupport') }}
|
||||
</video>
|
||||
<embed v-else :src="'data:' + binaryData.mimeType + ';base64,' + binaryData.data" class="binary-data" :class="embedClass"/>
|
||||
<BinaryDataDisplayEmbed v-else :binaryData="binaryData"/>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@@ -30,15 +26,22 @@ import {
|
||||
IRunExecutionData,
|
||||
} from 'n8n-workflow';
|
||||
|
||||
import BinaryDataDisplayEmbed from '@/components/BinaryDataDisplayEmbed.vue';
|
||||
|
||||
import { nodeHelpers } from '@/components/mixins/nodeHelpers';
|
||||
|
||||
import mixins from 'vue-typed-mixins';
|
||||
import { restApi } from '@/components/mixins/restApi';
|
||||
|
||||
export default mixins(
|
||||
nodeHelpers,
|
||||
restApi,
|
||||
)
|
||||
.extend({
|
||||
name: 'BinaryDataDisplay',
|
||||
components: {
|
||||
BinaryDataDisplayEmbed,
|
||||
},
|
||||
props: [
|
||||
'displayData', // IBinaryDisplayData
|
||||
'windowVisible', // boolean
|
||||
@@ -54,14 +57,15 @@ export default mixins(
|
||||
if (this.displayData.index >= binaryData.length || binaryData[this.displayData.index][this.displayData.key] === undefined) {
|
||||
return null;
|
||||
}
|
||||
return binaryData[this.displayData.index][this.displayData.key];
|
||||
|
||||
const binaryDataItem: IBinaryData = binaryData[this.displayData.index][this.displayData.key];
|
||||
|
||||
return binaryDataItem;
|
||||
},
|
||||
|
||||
embedClass (): string[] {
|
||||
if (this.binaryData !== null &&
|
||||
this.binaryData.mimeType !== undefined &&
|
||||
(this.binaryData.mimeType as string).startsWith('image')
|
||||
) {
|
||||
// @ts-ignore
|
||||
if (this.binaryData! !== null && this.binaryData!.mimeType! !== undefined && (this.binaryData!.mimeType! as string).startsWith('image')) {
|
||||
return ['image'];
|
||||
}
|
||||
return ['other'];
|
||||
|
||||
84
packages/editor-ui/src/components/BinaryDataDisplayEmbed.vue
Normal file
84
packages/editor-ui/src/components/BinaryDataDisplayEmbed.vue
Normal file
@@ -0,0 +1,84 @@
|
||||
<template>
|
||||
<div>
|
||||
<div v-if="isLoading">
|
||||
Loading binary data...
|
||||
</div>
|
||||
<div v-else-if="error">
|
||||
Error loading binary data
|
||||
</div>
|
||||
<div v-else>
|
||||
<video v-if="binaryData.mimeType && binaryData.mimeType.startsWith('video/')" controls autoplay>
|
||||
<source :src="embedSource" :type="binaryData.mimeType">
|
||||
{{ $locale.baseText('binaryDataDisplay.yourBrowserDoesNotSupport') }}
|
||||
</video>
|
||||
<embed v-else :src="embedSource" class="binary-data" :class="embedClass"/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
|
||||
|
||||
import mixins from 'vue-typed-mixins';
|
||||
import { restApi } from '@/components/mixins/restApi';
|
||||
|
||||
export default mixins(
|
||||
restApi,
|
||||
)
|
||||
.extend({
|
||||
name: 'BinaryDataDisplayEmbed',
|
||||
props: [
|
||||
'binaryData', // IBinaryDisplayData
|
||||
],
|
||||
data() {
|
||||
return {
|
||||
isLoading: true,
|
||||
embedSource: '',
|
||||
error: false,
|
||||
};
|
||||
},
|
||||
async mounted() {
|
||||
if(!this.binaryData.id) {
|
||||
this.embedSource = 'data:' + this.binaryData.mimeType + ';base64,' + this.binaryData.data;
|
||||
this.isLoading = false;
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const bufferString = await this.restApi().getBinaryBufferString(this.binaryData!.id!);
|
||||
this.embedSource = 'data:' + this.binaryData.mimeType + ';base64,' + bufferString;
|
||||
this.isLoading = false;
|
||||
} catch (e) {
|
||||
this.isLoading = false;
|
||||
this.error = true;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
embedClass (): string[] {
|
||||
// @ts-ignore
|
||||
if (this.binaryData! !== null && this.binaryData!.mimeType! !== undefined && (this.binaryData!.mimeType! as string).startsWith('image')) {
|
||||
return ['image'];
|
||||
}
|
||||
return ['other'];
|
||||
},
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
|
||||
.binary-data {
|
||||
background-color: #fff;
|
||||
|
||||
&.image {
|
||||
max-height: calc(100% - 1em);
|
||||
max-width: calc(100% - 1em);
|
||||
}
|
||||
|
||||
&.other {
|
||||
height: calc(100% - 1em);
|
||||
width: calc(100% - 1em);
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
@@ -192,6 +192,11 @@ export const restApi = Vue.extend({
|
||||
getTimezones: (): Promise<IDataObject> => {
|
||||
return self.restApi().makeRestApiRequest('GET', `/options/timezones`);
|
||||
},
|
||||
|
||||
// Binary data
|
||||
getBinaryBufferString: (dataPath: string): Promise<string> => {
|
||||
return self.restApi().makeRestApiRequest('GET', `/data/${dataPath}`);
|
||||
},
|
||||
};
|
||||
},
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user