diff --git a/packages/server/src/services/documentstore/index.ts b/packages/server/src/services/documentstore/index.ts index 845bf9f1f98..a850b5516ca 100644 --- a/packages/server/src/services/documentstore/index.ts +++ b/packages/server/src/services/documentstore/index.ts @@ -1850,18 +1850,12 @@ const upsertDocStore = async ( const mimePrefix = 'data:' + file.mimetype + ';base64' const storagePath = mimePrefix + ',' + fileBuffer.toString('base64') + `,filename:${file.originalname}` - const fileInputFieldFromMimeType = mapMimeTypeToInputField(file.mimetype) - const fileExtension = path.extname(file.originalname) - const fileInputFieldFromExt = mapExtToInputField(fileExtension) - - let fileInputField = 'txtFile' - - if (fileInputFieldFromExt !== 'txtFile') { - fileInputField = fileInputFieldFromExt - } else if (fileInputFieldFromMimeType !== 'txtFile') { - fileInputField = fileInputFieldFromExt + // Try to map by file extension first, fall back to MIME type if extension is not recognized + let fileInputField = mapExtToInputField(fileExtension) + if (fileInputField === 'txtFile') { + fileInputField = mapMimeTypeToInputField(file.mimetype) } if (loaderId === 'unstructuredFileLoader') { diff --git a/packages/server/src/utils/buildChatflow.ts b/packages/server/src/utils/buildChatflow.ts index c54c009c43a..711e925a927 100644 --- a/packages/server/src/utils/buildChatflow.ts +++ b/packages/server/src/utils/buildChatflow.ts @@ -437,18 +437,12 @@ export const executeFlow = async ({ ) await updateStorageUsage(orgId, workspaceId, totalSize, usageCacheManager) - const fileInputFieldFromMimeType = mapMimeTypeToInputField(file.mimetype) - const fileExtension = path.extname(file.originalname) - const fileInputFieldFromExt = mapExtToInputField(fileExtension) - - let fileInputField = 'txtFile' - - if (fileInputFieldFromExt !== 'txtFile') { - fileInputField = fileInputFieldFromExt - } else if (fileInputFieldFromMimeType !== 'txtFile') { - fileInputField = fileInputFieldFromExt + // Try to map by file extension first, fall back to MIME type if extension is not recognized + let fileInputField = mapExtToInputField(fileExtension) + if (fileInputField === 'txtFile') { + fileInputField = mapMimeTypeToInputField(file.mimetype) } if (overrideConfig[fileInputField]) { diff --git a/packages/server/src/utils/createAttachment.ts b/packages/server/src/utils/createAttachment.ts index 2daec1e2e1d..7ae03f945de 100644 --- a/packages/server/src/utils/createAttachment.ts +++ b/packages/server/src/utils/createAttachment.ts @@ -166,18 +166,12 @@ export const createFileAttachment = async (req: Request) => { ) await updateStorageUsage(orgId, workspaceId, totalSize, appServer.usageCacheManager) - const fileInputFieldFromMimeType = mapMimeTypeToInputField(file.mimetype) - const fileExtension = path.extname(file.originalname) - const fileInputFieldFromExt = mapExtToInputField(fileExtension) - - let fileInputField = 'txtFile' - - if (fileInputFieldFromExt !== 'txtFile') { - fileInputField = fileInputFieldFromExt - } else if (fileInputFieldFromMimeType !== 'txtFile') { - fileInputField = fileInputFieldFromExt + // Try to map by file extension first, fall back to MIME type if extension is not recognized + let fileInputField = mapExtToInputField(fileExtension) + if (fileInputField === 'txtFile') { + fileInputField = mapMimeTypeToInputField(file.mimetype) } await removeSpecificFileFromUpload(file.path ?? file.key) diff --git a/packages/server/src/utils/upsertVector.ts b/packages/server/src/utils/upsertVector.ts index b89e82928e0..2fee256ef60 100644 --- a/packages/server/src/utils/upsertVector.ts +++ b/packages/server/src/utils/upsertVector.ts @@ -85,18 +85,12 @@ export const executeUpsert = async ({ ) await updateStorageUsage(orgId, workspaceId, totalSize, usageCacheManager) - const fileInputFieldFromMimeType = mapMimeTypeToInputField(file.mimetype) - const fileExtension = path.extname(file.originalname) - const fileInputFieldFromExt = mapExtToInputField(fileExtension) - - let fileInputField = 'txtFile' - - if (fileInputFieldFromExt !== 'txtFile') { - fileInputField = fileInputFieldFromExt - } else if (fileInputFieldFromMimeType !== 'txtFile') { - fileInputField = fileInputFieldFromExt + // Try to map by file extension first, fall back to MIME type if extension is not recognized + let fileInputField = mapExtToInputField(fileExtension) + if (fileInputField === 'txtFile') { + fileInputField = mapMimeTypeToInputField(file.mimetype) } if (overrideConfig[fileInputField]) { diff --git a/packages/server/test/index.test.ts b/packages/server/test/index.test.ts index 8c038f44f62..c733bc9a7d9 100644 --- a/packages/server/test/index.test.ts +++ b/packages/server/test/index.test.ts @@ -3,6 +3,7 @@ import { getRunningExpressApp } from '../src/utils/getRunningExpressApp' import { organizationUserRouteTest } from './routes/v1/organization-user.route.test' import { userRouteTest } from './routes/v1/user.route.test' import { apiKeyTest } from './utils/api-key.util.test' +import { fileMappingTest } from './utils/file-mapping.util.test' // ⏱️ Extend test timeout to 6 minutes for long setups (increase as tests grow) jest.setTimeout(360000) @@ -25,4 +26,5 @@ describe('Routes Test', () => { describe('Utils Test', () => { apiKeyTest() + fileMappingTest() }) diff --git a/packages/server/test/utils/file-mapping.util.test.ts b/packages/server/test/utils/file-mapping.util.test.ts new file mode 100644 index 00000000000..69c48d4f248 --- /dev/null +++ b/packages/server/test/utils/file-mapping.util.test.ts @@ -0,0 +1,109 @@ +import { mapExtToInputField, mapMimeTypeToInputField } from 'flowise-components' + +export function fileMappingTest() { + describe('File Input Field Mapping', () => { + describe('Extension-based mapping', () => { + it('should map .pdf extension to pdfFile', () => { + const result = mapExtToInputField('.pdf') + expect(result).toEqual('pdfFile') + }) + + it('should map .docx extension to docxFile', () => { + const result = mapExtToInputField('.docx') + expect(result).toEqual('docxFile') + }) + + it('should map .xlsx extension to csvFile', () => { + const result = mapExtToInputField('.xlsx') + expect(result).toEqual('csvFile') + }) + + it('should return txtFile for unknown extensions', () => { + const result = mapExtToInputField('.unknown') + expect(result).toEqual('txtFile') + }) + }) + + describe('MIME type-based mapping', () => { + it('should map application/pdf to pdfFile', () => { + const result = mapMimeTypeToInputField('application/pdf') + expect(result).toEqual('pdfFile') + }) + + it('should map Word document MIME types to docxFile', () => { + expect(mapMimeTypeToInputField('application/vnd.openxmlformats-officedocument.wordprocessingml.document')).toEqual( + 'docxFile' + ) + expect(mapMimeTypeToInputField('application/msword')).toEqual('docxFile') + }) + + it('should map Excel MIME types to excelFile', () => { + expect(mapMimeTypeToInputField('application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')).toEqual( + 'excelFile' + ) + expect(mapMimeTypeToInputField('application/vnd.ms-excel')).toEqual('excelFile') + }) + + it('should return txtFile for unknown MIME types', () => { + const result = mapMimeTypeToInputField('application/unknown') + expect(result).toEqual('txtFile') + }) + }) + + describe('Fallback logic (regression test for PDF bug)', () => { + it('should correctly handle PDF files using fallback logic', () => { + // Simulate the file input field determination logic + const fileExtension = '.pdf' + const mimeType = 'application/pdf' + + // Try extension first + let fileInputField = mapExtToInputField(fileExtension) + + // Fall back to MIME type if extension returns txtFile + if (fileInputField === 'txtFile') { + fileInputField = mapMimeTypeToInputField(mimeType) + } + + // PDF should be correctly mapped to pdfFile + expect(fileInputField).toEqual('pdfFile') + }) + + it('should correctly handle Word documents using extension', () => { + const fileExtension = '.docx' + const mimeType = 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' + + let fileInputField = mapExtToInputField(fileExtension) + if (fileInputField === 'txtFile') { + fileInputField = mapMimeTypeToInputField(mimeType) + } + + expect(fileInputField).toEqual('docxFile') + }) + + it('should correctly handle Excel documents using extension', () => { + const fileExtension = '.xlsx' + const mimeType = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' + + let fileInputField = mapExtToInputField(fileExtension) + if (fileInputField === 'txtFile') { + fileInputField = mapMimeTypeToInputField(mimeType) + } + + expect(fileInputField).toEqual('csvFile') + }) + + it('should fall back to MIME type for unrecognized extensions', () => { + const fileExtension = '.unknown' + const mimeType = 'application/pdf' + + let fileInputField = mapExtToInputField(fileExtension) + if (fileInputField === 'txtFile') { + fileInputField = mapMimeTypeToInputField(mimeType) + } + + // Should use MIME type fallback and detect it as PDF + expect(fileInputField).toEqual('pdfFile') + }) + }) + }) +}