From cdab4c1bc698e3ebfffe7cd93eec3baa225062a8 Mon Sep 17 00:00:00 2001 From: luka Date: Wed, 11 Jun 2025 15:36:54 +0800 Subject: [PATCH] fix(editor): Fix the issue that the content of json, html, csv, md, txt, and css files contained garbled Chinese characters when clicking the view button (#16118) Co-authored-by: luka --- .../src/components/BinaryDataDisplayEmbed.vue | 9 ++++---- packages/workflow/src/index.ts | 1 + packages/workflow/src/utils.ts | 22 +++++++++++++++++++ 3 files changed, 28 insertions(+), 4 deletions(-) diff --git a/packages/frontend/editor-ui/src/components/BinaryDataDisplayEmbed.vue b/packages/frontend/editor-ui/src/components/BinaryDataDisplayEmbed.vue index 7b545beaf3..59fa8e677e 100644 --- a/packages/frontend/editor-ui/src/components/BinaryDataDisplayEmbed.vue +++ b/packages/frontend/editor-ui/src/components/BinaryDataDisplayEmbed.vue @@ -2,7 +2,7 @@ import { ref, onMounted, computed } from 'vue'; import { useWorkflowsStore } from '@/stores/workflows.store'; import type { IBinaryData } from 'n8n-workflow'; -import { jsonParse } from 'n8n-workflow'; +import { jsonParse, base64DecodeUTF8 } from 'n8n-workflow'; import VueJsonPretty from 'vue-json-pretty'; import RunDataHtml from '@/components/RunDataHtml.vue'; import { useI18n } from '@n8n/i18n'; @@ -28,12 +28,13 @@ onMounted(async () => { const { id, data: binaryData, fileName, fileType, mimeType } = props.binaryData; const isJSONData = fileType === 'json'; const isHTMLData = fileType === 'html'; - if (!id) { if (isJSONData || isHTMLData) { - data.value = jsonParse(atob(binaryData)); + data.value = isJSONData + ? jsonParse(base64DecodeUTF8(binaryData)) + : base64DecodeUTF8(binaryData); } else { - embedSource.value = 'data:' + mimeType + ';base64,' + binaryData; + embedSource.value = `data:${mimeType};charset=utf-8;base64,${binaryData}`; } } else { try { diff --git a/packages/workflow/src/index.ts b/packages/workflow/src/index.ts index ff95994efd..bcf9b2fc19 100644 --- a/packages/workflow/src/index.ts +++ b/packages/workflow/src/index.ts @@ -27,6 +27,7 @@ export { isObjectEmpty, deepCopy, jsonParse, + base64DecodeUTF8, jsonStringify, replaceCircularReferences, sleep, diff --git a/packages/workflow/src/utils.ts b/packages/workflow/src/utils.ts index df487d418b..5e48880010 100644 --- a/packages/workflow/src/utils.ts +++ b/packages/workflow/src/utils.ts @@ -155,6 +155,28 @@ type JSONStringifyOptions = { replaceCircularRefs?: boolean; }; +/** + * Decodes a Base64 string with proper UTF-8 character handling. + * + * @param str - The Base64 string to decode + * @returns The decoded UTF-8 string + */ +export const base64DecodeUTF8 = (str: string): string => { + try { + // Use modern TextDecoder for proper UTF-8 handling + const bytes = new Uint8Array( + atob(str) + .split('') + .map((char) => char.charCodeAt(0)), + ); + return new TextDecoder('utf-8').decode(bytes); + } catch (error) { + // Fallback method for older browsers + console.warn('TextDecoder not available, using fallback method'); + return atob(str); + } +}; + export const replaceCircularReferences = (value: T, knownObjects = new WeakSet()): T => { if (typeof value !== 'object' || value === null || value instanceof RegExp) return value; if ('toJSON' in value && typeof value.toJSON === 'function') return value.toJSON() as T;