From fbe9f34a60a1a7239079527e71cc6b3d7c55b6bc Mon Sep 17 00:00:00 2001 From: Henry Heng Date: Fri, 18 Jul 2025 19:08:02 +0100 Subject: [PATCH] Feature/Excel and PPT File Uploads (#4896) Enhance file upload capabilities by adding support for additional file types (html, css, js, xml, md, excel, powerpoint) and updating related MIME type mappings. Improve user interface for file type selection in FileUpload component. --- .../nodes/documentloaders/File/File.ts | 15 +++- packages/components/src/utils.ts | 27 +++++++ packages/server/src/utils/createAttachment.ts | 2 +- .../src/ui-component/extended/FileUpload.jsx | 77 +++++++++++-------- 4 files changed, 89 insertions(+), 32 deletions(-) diff --git a/packages/components/nodes/documentloaders/File/File.ts b/packages/components/nodes/documentloaders/File/File.ts index d3049553..53f5be5e 100644 --- a/packages/components/nodes/documentloaders/File/File.ts +++ b/packages/components/nodes/documentloaders/File/File.ts @@ -32,7 +32,7 @@ class File_DocumentLoaders implements INode { this.type = 'Document' this.icon = 'file.svg' this.category = 'Document Loaders' - this.description = `A generic file loader that can load txt, json, csv, docx, pdf, and other files` + this.description = `A generic file loader that can load different file types` this.baseClasses = [this.type] this.inputs = [ { @@ -214,6 +214,11 @@ class File_DocumentLoaders implements INode { json: (blob) => new JSONLoader(blob), jsonl: (blob) => new JSONLinesLoader(blob, '/' + pointerName.trim()), txt: (blob) => new TextLoader(blob), + html: (blob) => new TextLoader(blob), + css: (blob) => new TextLoader(blob), + js: (blob) => new TextLoader(blob), + xml: (blob) => new TextLoader(blob), + md: (blob) => new TextLoader(blob), csv: (blob) => new CSVLoader(blob), xls: (blob) => new LoadOfSheet(blob), xlsx: (blob) => new LoadOfSheet(blob), @@ -301,6 +306,8 @@ const getOverrideFileInputs = (nodeData: INodeData) => { const jsonlinesFileBase64 = nodeData.inputs?.jsonlinesFile as string const docxFileBase64 = nodeData.inputs?.docxFile as string const yamlFileBase64 = nodeData.inputs?.yamlFile as string + const excelFileBase64 = nodeData.inputs?.excelFile as string + const powerpointFileBase64 = nodeData.inputs?.powerpointFile as string const removePrefix = (storageFile: string): string[] => { const fileName = storageFile.replace('FILE-STORAGE::', '') @@ -333,6 +340,12 @@ const getOverrideFileInputs = (nodeData: INodeData) => { if (yamlFileBase64) { files.push(...removePrefix(yamlFileBase64)) } + if (excelFileBase64) { + files.push(...removePrefix(excelFileBase64)) + } + if (powerpointFileBase64) { + files.push(...removePrefix(powerpointFileBase64)) + } return files.length ? `FILE-STORAGE::${JSON.stringify(files)}` : '' } diff --git a/packages/components/src/utils.ts b/packages/components/src/utils.ts index 1f24fb81..5947d4fa 100644 --- a/packages/components/src/utils.ts +++ b/packages/components/src/utils.ts @@ -1070,7 +1070,17 @@ export const mapMimeTypeToInputField = (mimeType: string) => { case 'text/jsonl': return 'jsonlinesFile' case 'application/vnd.openxmlformats-officedocument.wordprocessingml.document': + case 'application/msword': { return 'docxFile' + } + case 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet': + case 'application/vnd.ms-excel': { + return 'excelFile' + } + case 'application/vnd.openxmlformats-officedocument.presentationml.presentation': + case 'application/vnd.ms-powerpoint': { + return 'powerpointFile' + } case 'application/vnd.yaml': case 'application/x-yaml': case 'text/vnd.yaml': @@ -1091,6 +1101,19 @@ export const mapMimeTypeToExt = (mimeType: string) => { switch (mimeType) { case 'text/plain': return 'txt' + case 'text/html': + return 'html' + case 'text/css': + return 'css' + case 'text/javascript': + case 'application/javascript': + return 'js' + case 'text/xml': + case 'application/xml': + return 'xml' + case 'text/markdown': + case 'text/x-markdown': + return 'md' case 'application/pdf': return 'pdf' case 'application/json': @@ -1109,6 +1132,10 @@ export const mapMimeTypeToExt = (mimeType: string) => { return 'xls' case 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet': return 'xlsx' + case 'application/vnd.ms-powerpoint': + return 'ppt' + case 'application/vnd.openxmlformats-officedocument.presentationml.presentation': + return 'pptx' default: return '' } diff --git a/packages/server/src/utils/createAttachment.ts b/packages/server/src/utils/createAttachment.ts index d1e7ceaa..1746cf9c 100644 --- a/packages/server/src/utils/createAttachment.ts +++ b/packages/server/src/utils/createAttachment.ts @@ -172,7 +172,7 @@ export const createFileAttachment = async (req: Request) => { content }) } catch (error) { - throw new Error(`Failed operation: createFileAttachment - ${getErrorMessage(error)}`) + throw new Error(`Failed createFileAttachment: ${file.originalname} (${file.mimetype} - ${getErrorMessage(error)}`) } } } diff --git a/packages/ui/src/ui-component/extended/FileUpload.jsx b/packages/ui/src/ui-component/extended/FileUpload.jsx index 2fdda35c..2555ee14 100644 --- a/packages/ui/src/ui-component/extended/FileUpload.jsx +++ b/packages/ui/src/ui-component/extended/FileUpload.jsx @@ -23,18 +23,20 @@ const message = `Uploaded files will be parsed as strings and sent to the LLM. I Refer docs for more details.` const availableFileTypes = [ - { name: 'CSS', ext: 'text/css' }, - { name: 'CSV', ext: 'text/csv' }, - { name: 'HTML', ext: 'text/html' }, - { name: 'JSON', ext: 'application/json' }, - { name: 'YAML', ext: 'application/x-yaml' }, - { name: 'Markdown', ext: 'text/markdown' }, - { name: 'PDF', ext: 'application/pdf' }, - { name: 'SQL', ext: 'application/sql' }, - { name: 'Text File', ext: 'text/plain' }, - { name: 'XML', ext: 'application/xml' }, - { name: 'DOC', ext: 'application/msword' }, - { name: 'DOCX', ext: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' } + { name: 'CSS', ext: 'text/css', extension: '.css' }, + { name: 'CSV', ext: 'text/csv', extension: '.csv' }, + { name: 'HTML', ext: 'text/html', extension: '.html' }, + { name: 'JSON', ext: 'application/json', extension: '.json' }, + { name: 'Markdown', ext: 'text/markdown', extension: '.md' }, + { name: 'YAML', ext: 'application/x-yaml', extension: '.yaml' }, + { name: 'PDF', ext: 'application/pdf', extension: '.pdf' }, + { name: 'SQL', ext: 'application/sql', extension: '.sql' }, + { name: 'Text File', ext: 'text/plain', extension: '.txt' }, + { name: 'XML', ext: 'application/xml', extension: '.xml' }, + { name: 'DOC', ext: 'application/msword', extension: '.doc' }, + { name: 'DOCX', ext: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', extension: '.docx' }, + { name: 'XLSX', ext: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', extension: '.xlsx' }, + { name: 'PPTX', ext: 'application/vnd.openxmlformats-officedocument.presentationml.presentation', extension: '.pptx' } ] const FileUpload = ({ dialogProps }) => { @@ -222,30 +224,45 @@ const FileUpload = ({ dialogProps }) => { onChange={handleAllowedFileTypesChange} /> ))} - - PDF Usage - - - } label='One document per page' /> - } label='One document per file' /> - - - + {allowedFileTypes.includes('application/pdf') && fullFileUpload && ( + + PDF Configuration - - - + + PDF Usage + + + } label='One document per page' /> + } label='One document per file' /> + + + + + + + + + )} Save